基於elasticsearch的搜尋自動糾錯
作者: 馬努
elasticsearch是一個全文搜尋引擎,能在大量資料中提供快速、準確的檢索,同時它也提供了一些改善搜尋體驗的功能。如下兩張圖所示,我們在搜尋的時候經常會因為手誤或者不確定,出現輸入的搜尋關鍵字錯誤的情況,當前流行的谷歌和百度都會給出提示,“以下為您顯示”或者“Showing results for”,本文解釋如何用suggest api更正搜尋中的拼寫,提供搜尋建議功能。
準備測試資料
我們索引一些測試資料,來說明糾錯建議的實現,以下是我們準備的測試資料。
curl -XPOST localhost:9200/suggester_test/my_type/_bulk -d '
{" index": {"_id": 1}}
{"testfield": "Elasticsearch is based on lucene"}
{"index": {"_id": 2}}
{"testfield": "Elasticsearch is based on lucne"}
{"index": {"_id": 3}}
{"testfield": "Elasticsearch and solr are based on lucene"}
{"index": {"_id": 4}}
{"testfield": "Elasticsearch is open source"}
{"index": {" _id": 5}}
{"testfield": "Elasticserch is open source"}
'
term suggester
term suggester基於編輯距離的匹配查詢,建議的文字在查詢之前進行分詞,根據分詞的結果得到每個詞的建議結果。如下查詢:
curl -XPOST localhost:9200/suggester_test/_search?pretty -d '{
"size": 0,
"suggest": {
"text": "elasticsrch lucene",
"my-suggestion": {
"term": {
" field": "testfield",
"suggest_mode": "always"
}
}
}
}'
我們查詢“Elasticsrch lucene”,其term suggest結果如下
{
"took" : 26,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 5,
"max_score" : 0.0,
"hits" : [ ]
},
"suggest" : {
"my-suggestion" : [ {
"text" : "elasticsrch",
"offset" : 0,
"length" : 11,
"options" : [ {
"text" : "elasticserch",
"score" : 0.9090909,
"freq" : 1
}, {
"text" : "elasticsearch",
"score" : 0.8181818,
"freq" : 3
} ]
}, {
"text" : "lucene",
"offset" : 12,
"length" : 6,
"options" : [ {
"text" : "lucne",
"score" : 0.8,
"freq" : 1
} ]
} ]
}
}
“elasticsrch lucene”經過分詞之後產生了elasticsrch 和lucene兩個詞根,得到的建議結果分別是elasticsrch, elasticsearch和lucne(此處為了說明情況,特意索引了拼寫相似的單詞)。elasticsrch的糾正結果是elasticserch和elasticsearch其中elasticserch更相似,假如實際中搜索建議給出了兩個相似拼寫的建議值,我們不能確定那個更合適;對於lecene得到lucne,因為我們庫中的髒資料給出了錯誤的建議。如果庫中資料存在髒資料,對於term suggest會起到反作用,對正確的資料給出錯誤的建議。
phrase suggester
phrase suggester在term suggester之上添加了額外的邏輯以選擇整體更正的phrase,而不是基於單個分詞加權的ngram語言模型。在實際中phrase suggester能夠根據單詞的詞頻等資訊作出更好的選擇。
curl -XPOST localhost:9200/suggester_test/_search?pretty -d '{
"size": 0,
"suggest": {
"text": "elasticsrch lucene",
"my-suggestion": {
"phrase": {
"field": "testfield",
"confidence": 0,
"collate": {
"query": {
"inline": {
"match": {
"{{field_name}}" : "{{suggestion}}"
}
}
},
"params": {"field_name" : "testfield"},
"prune": true
}
}
}
}
}'
查詢結果如下:
{
"took" : 23,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 5,
"max_score" : 0.0,
"hits" : [ ]
},
"suggest" : {
"my-suggestion" : [ {
"text" : "elasticsrch lucene",
"offset" : 0,
"length" : 18,
"options" : [ {
"text" : "elasticsearch lucene",
"score" : 0.2214925,
"collate_match" : true
}, {
"text" : "elasticserch lucene",
"score" : 0.20829101,
"collate_match" : true
}, {
"text" : "elasticsrch lucene",
"score" : 0.17490317,
"collate_match" : false
}, {
"text" : "elasticsrch lucne",
"score" : 0.10791662,
"collate_match" : true
} ]
} ]
}
}
查詢結果給出單個詞根糾錯結果的所有組合,並且給出了collate_match屬性,collate_match是collate條件產生的,collate會將當前的建議自動變為{{suggestion}}變數進行指定查詢,如果prune設定為true時,這些建議將有一個額外的選項collate_match,如果找到了與短語匹配的文件,該選項將為true,否則為false。我們可以根據_score和prune對建議結果進行篩選,給出搜尋建議。
總結
本文主要介紹李suggest api的使用,並結合實際場景分析李如何利用suggest api實現搜尋中的自動糾錯建議。