本文讨论了在特定情况下如何使用单个CALL QSUGGEST来修正短语。
CALL QSUGGEST 是在Sphinx 2.x的最新版本中引入的。该语句允许从启用了前缀匹配的索引字典中查找输入单词的近似匹配。此功能最常见的使用场景是实现“您是否是指...?”的功能。
在QSUGGEST引入之前,要实现“您是否是指...?”功能,需要从索引字典中提取单词,并将单词的三元组放入单独的索引中。然后通过搜索输入单词的三元组来执行此操作。随后,为了提高返回结果的质量,会计算返回匹配项的莱文斯坦距离。CALL QSUGGEST消除了这一需求,因为它不需要单独的索引,同时也提供了莱文斯坦距离计算,不仅消除了对另一个索引的需求(这还需要定期刷新),还消除了实现此功能所需的额外代码。
尽管CALL QSUGGEST允许在输入时接收多个单词,但它只会针对最后一个单词提供建议并忽略其余部分。其对应功能-
CALL SUGGEST
则使用第一个单词并忽略其余部分。如果我们希望对多个单词进行建议,首选方法是执行多次QSUGGEST调用。但在某些情况下,输入可能是一个由多个单词组成的特定术语或分类法(例如产品SKU或标签),或者是一个被用户错误拆分的单词。在这些情况下可以使用单个QSUGGEST。
正如我们上面所说,CALL QSUGGEST基于三元组。如果我们尝试匹配由多个单词组成的术语,我们可以将现有的空格作为可索引字符,这将给我们一个QSUGGEST可以处理的单个“单词”。例如,我们可以将空格替换为下划线,而下划线包含在默认的 charset_table 中。要使此方法生效,我们需要在索引中添加这些术语的额外版本,其中空格(或其他不可索引字符)将被替换为可索引字符。另一种方法是直接删除空格,但可能会导致不同术语具有相同的标记。
在这个快速示例中,我们使用了维基百科文章的转储,其中我们索引了文章标题的单独版本,其中空格被替换为下划线。
在第一个示例中,我们将错误拼写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.