在實際的搜索中,我們有時候會打錯字,從而導致搜索不到。在Elasticsearch中,我們可以使用fuzziness屬性來進行模糊查詢,從而達到搜索有錯別字的情形。
match查詢具有“fuziness”屬性。它可以被設置為“0”, “1”, “2”或“auto”。“auto”是推薦的選項,它會根據查詢詞的長度定義距離。
Fuzzy query
返回包含與搜索詞相似的詞的文檔,以Levenshtein編輯距離測量。
編輯距離是將一個術語轉換為另一個術語所需的一個字符更改的次數。 這些更改可以包括:
- 更改字符(box→fox)
- 刪除字符(black→lack)
- 插入字符(sic→sick)
- 轉置兩個相鄰字符(act→cat)
為了找到相似的詞,模糊查詢會在指定的編輯距離內創建搜索詞的所有可能變化或擴展的集合。 查詢然后返回每個擴展的完全匹配。
例子
我們首先輸入如下的一個文檔到fuzzyindex索引中:
PUT fuzzyindex/_doc/1
{
"content": "I like blue sky"
}
如果這個時候,我們進行如下的搜索:
GET fuzzyindex/_search
{
"query": {
"match": {
"content": "ski"
}
}
}
那么是沒有任何被搜索到的結果,這是因為“I like blue sky" 里分詞后沒有ski這個詞。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
這個時候,如果我們使用如下的搜索:
GET fuzzyindex/_search
{
"query": {
"match": {
"content": {
"query": "ski",
"fuzziness": "1"
}
}
}
}
那么顯示的結果是:
{
"took" : 18,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.19178805,
"hits" : [
{
"_index" : "fuzzyindex",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.19178805,
"_source" : {
"content" : "I like blue sky"
}
}
]
}
}
顯然是找到我們需要的結果了。這是因為sky和ski時間上是只差別一個字母。
同樣,如果我們選用“auto”選項看看:
GET fuzzyindex/_search
{
"query": {
"match": {
"content": {
"query": "ski",
"fuzziness": "auto"
}
}
}
}
它顯示的結果和上面的是一樣的。也可以進行匹配。
如果我們進行如下的匹配:
GET fuzzyindex/_search
{
"query": {
"match": {
"content": {
"query": "bxxe",
"fuzziness": "auto"
}
}
}
}
那么它不能匹配任何的結果,但是,如果我們進行如下的搜索:
GET fuzzyindex/_search
{
"query": {
"match": {
"content": {
"query": "bxxe",
"fuzziness": "2"
}
}
}
}
我們也可以使用如下的格式:
GET /_search
{
"query": {
"fuzzy": {
"content": {
"value": "bxxe",
"fuzziness": "2"
}
}
}
}
那么它可以顯示搜索的結果,這是因為我們能夠容許兩個編輯的錯誤。
模糊性是拼寫錯誤的簡單解決方案,但具有很高的CPU開銷和非常低的精度。
參考:
【1】https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-fuzzy-query.html