我正在实现Web应用中的搜索建议功能,并一直在研究使用的技术中已有的实现。
似乎大多数主要网站(如Amazon、Bing等)都是以以下方式实现模糊搜索:
Tokenize search string in to terms
processingSearchStringSet = {}
For each term
if exact term is NOT in index
Get possible terms (fuzzyTerms) from levenshtein(term, 1 (or 2))
For each term in fuzzyTerms
if term is in index
processingSearchStringSet.intersect(stringsIndexedByTermsSet)
else
processingSearchStringSet.intersect(stringsIndexedByTermsSet)
从搜索结果来看,成员们可能会根据指标进行排名(例如:保留术语顺序、绝对术语位置、搜索热度),并根据这个排名和预先确定的结果集大小进行保留或消除,然后再返回给用户。
而谷歌的实现则与此有很大不同。
具体来说,它允许在搜索字符串的组成项中出现多于1个的错误。错误阈值似乎取决于感兴趣的项在字符串中的位置,但永远不会超过7个。
有趣的是:
- 使用Levenstein搜索在整个术语空间上进行阈值为5的搜索,对于用户字符串中的每个术语都将非常昂贵
- 即使执行了#1,仍无法解释错误建议的缺失
N-grams也似乎没有被使用:修改一个术语以使其不包含原始术语中存在的bigram似乎不会影响结果。
以下是一个例子,用于说明我的发现:
Example term: "Fiftyyyy shades of grey"
Amazon suggestions: none
(if the error count exceeds 1 on any term, the search fails)
Bing suggestions: none
(if the error count exceeds 2 on any term, the search fails)
Google suggestions: 10 (max)
(breaking the search would require 5 or more errors on any single term,
or multiple errors on multiple terms)
我的问题是:这里使用的是什么魔法?他们只是使用具有巨大误差容限的Levenshtein搜索,还是使用我不知道的其他技术?