模糊性
模糊匹配 对待 “模糊” 相似的两个词似乎是同一个词。 首先,我们需要对我们所说的 模糊性 进行定义。
在1965年,Vladimir Levenshtein 开发出了 Levenshtein distance, 用来度量从一个单词转换到另一个单词需要多少次单字符编辑。他提出了三种类型的单字符编辑:
- 一个字符 替换 另一个字符: _f_ox → _b_ox
- 插入 一个新的字符:sic → sic_k_
- 删除 一个字符:b_l_ack → back
Frederick Damerau 后来在这些操作基础上做了一个扩展:
- 相邻两个字符的 换位 : _st_ar → _ts_ar
举个例子,将单词 bieber
转换成 beaver
需要下面几个步骤:
- 把
b
替换成v
:bie_b_er → bie_v_er - 把
i
替换成a
:b_i_ever → b_a_ ever - 把
e
和a
进行换位:b_ae_ver → b_ea_ver
这三个步骤表示 Damerau-Levenshtein edit distance 编辑距离为 3 。
显然,从 beaver
转换成 bieber
是一个很长的过程—他们相距甚远而不能视为一个简单的拼写错误。 Damerau 发现 80% 的拼写错误编辑距离为 1 。换句话说, 80% 的拼写错误可以对原始字符串用 单次编辑 进行修正。
Elasticsearch 指定了 fuzziness
参数支持对最大编辑距离的配置,默认为 2 。
当然,单次编辑对字符串的影响取决于字符串的长度。对单词 hat
两次编辑能够产生 mad
, 所以对一个只有 3 个字符长度的字符串允许两次编辑显然太多了。 fuzziness
参数可以被设置为 AUTO
,这将导致以下的最大编辑距离:
- 字符串只有 1 到 2 个字符时是
0
- 字符串有 3 、 4 或者 5 个字符时是
1
- 字符串大于 5 个字符时是
2
当然,你可能会发现编辑距离 2
仍然是太多了,返回的结果似乎并不相关。 把最大 fuzziness
设置为 1
,你可以得到更好的结果和更好的性能。
模糊查询1
fuzzy
查询是 term
查询的模糊等价。 也许你很少直接使用它,但是理解它是如何工作的,可以帮助你在更高级别的 match
查询中使用模糊性。
现在我们可以为词 surprize
运行一个 fuzzy
查询:
GET /my_index/my_type/_search
{
"query": {
"fuzzy": {
"text": "surprize"
}
}
}
fuzzy
查询是一个词项级别的查询,所以它不做任何分析。它通过某个词项以及指定的 fuzziness
查找到词典中所有的词项。 fuzziness
默认设置为 AUTO
。
GET /my_index/my_type/_search
{
"query": {
"fuzzy": {
"text": {
"value": "surprize",
"fuzziness": 1
}
}
}
}
模糊匹配查询2
match
查询支持 开箱即用的模糊匹配:
# 简单使用:
{
"query": {
"match": {
"goodsName": {
"query": "JY60177",
"fuzziness": 1
}
}
}
}
GET /my_index/my_type/_search
{
"query": {
"match": {
"text": {
"query": "SURPRIZE ME!",
"fuzziness": "AUTO",
"operator": "and"
}
}
}
}
查询字符串首先进行分析,会产生词项 [surprize, me]
,并且每个词项根据指定的 fuzziness
进行模糊化。
同样, multi_match
查询也 支持 fuzziness
,但只有当执行查询时类型是 best_fields
或者 most_fields
:
GET /my_index/my_type/_search
{
"query": {
"multi_match": {
"fields": [ "text", "title" ],
"query": "SURPRIZE ME!",
"fuzziness": "AUTO"
}
}
}
match
和 multi_match
查询都支持 prefix_length
和 max_expansions
参数。
模糊性(Fuzziness)只能在 match
and multi_match
查询中使用。不能使用在短语匹配、常用词项或 cross_fields
匹配。
提高性能
fuzzy
查询的工作原理是给定原始词项及构造一个 编辑自动机— 像表示所有原始字符串指定编辑距离的字符串的一个大图表。
然后模糊查询使用这个自动机依次高效遍历词典中的所有词项以确定是否匹配。 一旦收集了词典中存在的所有匹配项,就可以计算匹配文档列表。
当然,根据存储在索引中的数据类型,一个编辑距离 2 的模糊查询能够匹配一个非常大数量的词项同时执行效率会非常糟糕。 下面两个参数可以用来限制对性能的影响:
prefix_length
不能被 “模糊化” 的初始字符数。 大部分的拼写错误发生在词的结尾,而不是词的开始。 例如通过将 prefix_length
设置为 3
,你可能够显著降低匹配的词项数量。
max_expansions
如果一个模糊查询扩展了三个或四个模糊选项, 这些新的模糊选项也许是有意义的。如 果它产生 1000 个模糊选项,那么就基本没有意义了。 设置 max_expansions
用来限制将产生的模糊选项的总数量。模糊查询将收集匹配词项直到达到 max_expansions
的限制。