一個(gè)線上問(wèn)題引發(fā)的思考——Elasticsearch 8.X 如何實(shí)現(xiàn)更精準(zhǔn)的檢索?
1、線上問(wèn)題

——問(wèn)題來(lái)自:死磕Elasticsearch 知識(shí)星球微信群
這個(gè)問(wèn)題涉及到業(yè)務(wù)細(xì)節(jié),至今沒(méi)有定論。不過(guò),該問(wèn)題引發(fā)了我的思考。
2、我的一點(diǎn)思考
我們使用 Elasticsearch 到底用來(lái)做什么?
除了 Elasticsearch 早已不是10年前因“菜譜”而火出技術(shù)圈的搜索引擎組件,它早已不是“單兵作戰(zhàn)”,而是 ELKB 形成的 Elastic Stack “行走江湖”。

但,至少技術(shù)選型涉及到大數(shù)據(jù)的檢索幾乎無(wú)一例外 Elasticsearch 都是“首發(fā)陣容”。
2.1 關(guān)于全文檢索,用戶(hù)更關(guān)注什么?
關(guān)于全文搜索,《這就是搜索引擎》張俊林博士從搜索引擎的角度闡述了用戶(hù)的關(guān)注點(diǎn),核心就是兩個(gè)。
其一:精準(zhǔn)率; 其二:召回率。
通俗點(diǎn)講:
精準(zhǔn)率是站在用戶(hù)角度,召回的數(shù)據(jù)貼合用戶(hù)的預(yù)期,越準(zhǔn)確越好。
當(dāng)然,大數(shù)據(jù)時(shí)代的今天,單純的字、詞匹配早已跟不上時(shí)代的步伐,基于用戶(hù)行為的推薦(如:抖音、網(wǎng)易云音樂(lè))往往更吊起用戶(hù)的胃口。

而召回率是滿(mǎn)足檢索條件的語(yǔ)句都盡可能的召回,到底要什么,讓用戶(hù)在結(jié)果中二次再做選擇。
這兩種都有應(yīng)用場(chǎng)景,無(wú)所謂誰(shuí)對(duì)誰(shuí)錯(cuò)。
提到 Elasticsearch 精準(zhǔn)召回?cái)?shù)據(jù),先不談“精準(zhǔn)”,先說(shuō)一下召回。
如下圖所示,可以分兩部分看:數(shù)據(jù)的寫(xiě)入過(guò)程、數(shù)據(jù)檢索過(guò)程。

數(shù)據(jù)寫(xiě)入過(guò)程要比圖中復(fù)雜,我們著重關(guān)注建立倒排索引的過(guò)程,因?yàn)楹竺嫖覀円诘古潘饕鋈臋z索。
2.2 數(shù)據(jù)寫(xiě)入過(guò)程
寫(xiě)入的文本如下:

基于 ik_smart 分詞后,倒排索引的中的分詞詞典如下所示:

2.3 數(shù)據(jù)檢索過(guò)程
Elasticsearch 提到檢索,這其實(shí)是一個(gè)大的概念,不信你看下面的腦圖。

Elasticsearch 檢索從大的角度可以看成黑盒,類(lèi)似:Google、baidu 搜索框。用戶(hù)搜索框輸入內(nèi)容,檢索召回?cái)?shù)據(jù)。
但是,技術(shù)人員的眼里看搜索,更關(guān)注用哪種類(lèi)型搜索。這涉及到檢索分類(lèi)。
Elasticsearch 檢索大致可以分為:全文檢索、精準(zhǔn)匹配檢索、多表關(guān)聯(lián)檢索、組合檢索、不常用檢索。
精準(zhǔn)匹配檢索回答的是“是和否、存在或不存在”問(wèn)題?比如:小明的手機(jī)號(hào)為:“13566668888”,多一位、少一位、錯(cuò)一位都不能被召回!完全滿(mǎn)足檢索條件就召回,不滿(mǎn)足檢索條件就不要召回。不存在中間情況。
而全文檢索回答的是“相關(guān)度”的問(wèn)題?如文章開(kāi)頭提到的“手表”、“手表帶”、“表帶”就有相關(guān)度,哪些數(shù)據(jù)該召回?誰(shuí)優(yōu)先被召回(也就是誰(shuí)排在前面)。
match_phrase 和 match 等實(shí)現(xiàn)檢索的機(jī)制是不一樣的,“profile:true" API 能幫我們更精細(xì)的看到底層的實(shí)現(xiàn)。
簡(jiǎn)單點(diǎn)說(shuō):match_phrase 走的是短語(yǔ)檢索匹配,而 match 走的是多字段拆解后的 term query 的 bool 語(yǔ)句組合體。


2.4 如何理解精準(zhǔn)?
其實(shí)這個(gè)沒(méi)有普適的標(biāo)準(zhǔn),不同的業(yè)務(wù)系統(tǒng)是不一樣的。
建議,結(jié)合業(yè)務(wù)需求、產(chǎn)品經(jīng)理和技術(shù)經(jīng)理、項(xiàng)目經(jīng)理、核心技術(shù)人員共同敲定。
滿(mǎn)足用戶(hù)要求的“精準(zhǔn)”才算是精準(zhǔn)。
比如文章開(kāi)頭提到的“手表”,其實(shí)有多種理解?
其一:只有“手表”兩個(gè)字,沒(méi)有任何其他,這種叫精準(zhǔn)。
其二:分詞詞典里有“手表”,就要召回,這種也叫精準(zhǔn)。
其三:只要文本里有就要召回,這也是某種意義的精準(zhǔn)。比如:“南京市長(zhǎng)江大橋”,搜索“江大橋”也要求召回。
等等......不一而足。
有了上面的思考,我們嘗試解讀一下開(kāi)篇的問(wèn)題。
3、Elasticsearch 8.X 更精準(zhǔn)檢索實(shí)現(xiàn)
如下示例,拿數(shù)據(jù)說(shuō)話!
3.1 字詞混合索引檢索方案
詞索引——使用 ik_smart 分詞。 字索引——使用 standard 標(biāo)準(zhǔn)分詞。
保留了 keyword 類(lèi)型,便于方案二的精準(zhǔn)字符匹配。
DELETE test-20220928
PUT test-20220928
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_smart",
"fields": {
"standard": {
"type": "text",
"analyzer": "standard"
},
"keyword": {
"type": "keyword"
}
}
}
}
}
}
POST test-20220928/_bulk
{"index":{"_id":1}}
{"title":"手表帶真好看"}
{"index":{"_id":2}}
{"title":"手表最近賣(mài)的不好,咋整"}
{"index":{"_id":3}}
{"title":"卡西歐手表不錯(cuò)哦"}
{"index":{"_id":4}}
{"title":"手表"}
先看“手表帶真好看”這個(gè)文檔 ik_smart 的分詞結(jié)果。
其他幾個(gè)文檔{“2”,“3”,“4”} 都包含手表的分詞,大家可以自己驗(yàn)證,篇幅原因,沒(méi)有截圖。

如下檢索是 bool 組合混合體。
對(duì)于:must 條件要求單字相連的多字(可以理解為短語(yǔ),但不見(jiàn)得是有意義的短語(yǔ),如:江大橋)必須滿(mǎn)足,用 短語(yǔ) match_phrase 進(jìn)行檢索。
對(duì)于:should 條件滿(mǎn)足 ik_smart 分詞存在結(jié)果,則召回?cái)?shù)據(jù),且極大的提升評(píng)分權(quán)重。
POST test-20220928/_search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"title": {
"query": "手表",
"boost": 50
}
}
}
],
"must": [
{
"match": {
"title.standard": "手表"
}
}
]
}
}
}
明顯看出來(lái):包含手表要排在前面。

3.2 自定義評(píng)分實(shí)現(xiàn)精準(zhǔn)檢索
使用前提:針對(duì)是 keyword 類(lèi)型。
大家記?。簊ort 排序、aggregation 聚合、script 腳本都只能針對(duì) keyword 類(lèi)型,text 類(lèi)型都是不支持的,除非開(kāi)啟“fielddata”(必要性非常小,使用場(chǎng)景也小,不建議開(kāi)啟)。
如下腳本的含義,如果字段精準(zhǔn)匹配,沒(méi)有多余字符,則評(píng)分極高,設(shè)置為1000;如果字段以給定關(guān)鍵詞開(kāi)頭,則評(píng)分高,設(shè)置為500;如果屬于包含關(guān)系,則評(píng)分也較高,設(shè)置為100;如果沒(méi)有包含,那評(píng)分為10。
POST test-20220928/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": "if(doc['title.keyword'].value == params.keyword) { return 1000; } else if(doc['title.keyword'].value.startsWith(params.keyword)){ return 500; } else if(doc['title.keyword'].value.contains(params.keyword)) { return 100; } else { return 10;}",
"params": {
"keyword": "手表"
}
}
}
}
}
相當(dāng)于我們?nèi)斯じ深A(yù)了評(píng)分,基于字段精準(zhǔn)匹配的情況實(shí)現(xiàn)了評(píng)分的區(qū)分。這樣,最先召回的結(jié)果數(shù)據(jù)就是我們最期望的精準(zhǔn)匹配結(jié)果了。

4、小結(jié)
針對(duì)企業(yè)級(jí)實(shí)戰(zhàn)問(wèn)題,引發(fā)了思考,并根據(jù)思考嘗試做了解答。
當(dāng)然,這道業(yè)務(wù)題目會(huì)有具體的細(xì)節(jié)業(yè)務(wù)場(chǎng)景,還需要進(jìn)一步溝通交流。
本文涉及的技術(shù)點(diǎn)都不復(fù)雜。包含如下:
分詞(中文分詞器、默認(rèn)分詞器) 組合分詞(fields) 組合檢索 排序(評(píng)分)+ 全文檢索+召回 自定義評(píng)分(自己定義的規(guī)則來(lái)進(jìn)行數(shù)據(jù)的評(píng)分,進(jìn)而將評(píng)分高的優(yōu)先返回,排在前面進(jìn)行返回?。?/span>
僅就本文的討論和實(shí)現(xiàn),相信你也遇到過(guò)類(lèi)似問(wèn)題,歡迎留言交流下你的思考!
推薦

