⚠️ 此页面为自动翻译,翻译可能不完美。

Suggestions on phrases using a single SUGGEST call

author image

本文讨论了在特定情况下如何使用单个CALL QSUGGEST来修正短语。

CALL QSUGGEST 是在Sphinx 2.x的最新版本中引入的。该语句允许从启用了前缀匹配的索引字典中查找输入单词的近似匹配。此功能最常见的使用场景是实现“您是否是指...?”的功能。

在引入 QSUGGEST 之前,要实现“Did you mean ...?”,需要从索引词典中提取词语,并把这些词语的三元组放到一个单独的索引中。随后会针对输入词的 trigrams 在这个索引上执行搜索。作为后续步骤,为了提升返回结果的质量,还会对匹配到的结果计算 Levenshtein distances
CALL QSUGGEST 消除了这些步骤,因为它不需要单独的索引,并且还提供 Levenshtein 计算;这不仅免去了另建索引的需求(而且那个索引还需要不时刷新),也省去了实现该功能所需的额外代码。

正如我们上面所说,CALL QSUGGEST基于三元组。如果我们尝试匹配由多个单词组成的术语,我们可以将现有的空格作为可索引字符,这将给我们一个QSUGGEST可以处理的单个“单词”。例如,我们可以将空格替换为下划线,而下划线包含在默认的 charset_table 中。要使此方法生效,我们需要在索引中添加这些术语的额外版本,其中空格(或其他不可索引字符)将被替换为可索引字符。另一种方法是直接删除空格,但可能会导致不同术语具有相同的标记。

正如上面所说,CALL QSUGGEST 基于三元组。如果我们要匹配由多个词组成的术语,可以把现有空白字符作为可索引字符,这样就能得到一个 QSUGGEST 可以处理的单个“词”。例如,我们可以用下划线替换空白字符,而下划线包含在默认的 charset_table 中。要让这套方案生效,我们需要在索引中为这些术语增加一个额外版本,把空白字符(或其他不可索引字符)替换成可索引字符。另一种做法是直接删除空白字符,但这样不同术语最终可能会得到相同的 token。

在第一个示例中,我们将错误拼写Manticore Search主要支持者之一的名称-Craigslist。错误的术语来自实际搜索我们的网站时的查询:

mysql> CALL QSUGGEST('craig_list','wikititles', 1 as non_char);


+--------------+----------+------+
| suggest      | distance | docs |
+--------------+----------+------+
| craigslist   | 1        | 1    |
| craig_first  | 2        | 1    |
| craig_zisk   | 2        | 1    |
| craig_ellis  | 3        | 1    |
| craig_ellis_ | 3        | 1    |
+--------------+----------+------+
5 rows in set (0.09 sec)
mysql> CALL QSUGGEST('crages_list','wikititles', 1 as non_char);

+--------------+----------+------+
| suggest      | distance | docs |
+--------------+----------+------+
| craigslist   | 3        | 1    |
| swadesh_list | 4        | 2    |
| danger_list  | 4        | 1    |
| dean_s_list  | 4        | 1    |
| lrus_list    | 4        | 1    |
+--------------+----------+------+
5 rows in set (0.13 sec)
mysql> CALL QSUGGEST('crag_list','wikititles', 1 as non_char);


+------------+----------+------+
| suggest | distance | docs |
+------------+----------+------+
| craigslist | 2 | 1 |
| craig_zisk | 3 | 1 |
| brad_listi | 3 | 1 |
| army_list | 3 | 1 |
| cratylism | 3 | 1 |
+------------+----------+------+
5 rows in set (0.03 sec)
相反的情况是当用户没有在单词之间输入空格,导致最终得到一个单词而不是两个。

mysql> CALL QSUGGEST('starwars','wikititles', 1 as non_char);


+------------+----------+------+
| suggest    | distance | docs |
+------------+----------+------+
| star_wars  | 1        | 108  |
| starways   | 1        | 1    |
| star_wars_ | 2        | 8    |
| stakkars   | 2        | 1    |
| stalwart   | 2        | 1    |
+------------+----------+------+
5 rows in set (0.01 sec)
我们也可以同时错误两个单词:

mysql> CALL QSUGGEST('abaham_lincol','wikititles', 1 as non_char);


+-----------------+----------+------+
| suggest | distance | docs |
+-----------------+----------+------+
| abraham_lincoln | 2 | 1 |
| abraham_sinkov | 4 | 1 |
+-----------------+----------+------+
2 rows in set (0.14 sec)
由于QSUGGEST应用了莱文斯坦距离,单词的顺序很重要,按相反顺序检查术语将不会得到预期结果,例如:

mysql> CALL QSUGGEST('lincol_abaham','wikititles', 1 as non_char);


+---------------+----------+------+
| suggest | distance | docs |
+---------------+----------+------+
| lincoln_isham | 4 | 1 |
+---------------+----------+------+
1 row in set (0.14 sec)
对于这种情况,应为每个单词使用QSUGGEST调用,或者如果术语可以从索引中单独提取,则应使用三元组搜索。

For this case, a QSUGGEST call for each word should be used or if the terms can be extracted separate from the index, a trigram searching should be used.

安装Manticore Search

安装Manticore Search