content是一個text類型,用的 ik_max_word 分的詞,需要根據關鍵詞做精準匹配,并且按照發布時間倒序。
比如我搜:小米6s,搜出來的結果要精確匹配到:小米6s,并且按照用戶的發布時間倒序排序。
現在的問題是用 match_pharse 搜索的時候,有時候文檔里明明有這個關鍵詞,但是搜不出來,嘗試了好幾種手段......
熟悉咱們公眾號推文的同學應該知道,咱們分別在 2018年、2020年、2022年 都做過多次類似問題的討論。
探究 | 明明存在,怎么搜索不出來呢?
Elasticsearch能檢索出來,但不能正確高亮怎么辦?
由 Elasticsearch 空間換時間的線上問題說開去......
數據索引化的過程是借助分詞器完成的,如讀者的分詞器是 IK 中文分詞器。
問題來了?IK 中文分詞器能包含全部的詞匯嗎?
大家看 medcl 大佬開源的 IK 分詞器的源碼中能找到 main.dic 大小是 2.92 MB。并且這個詞典 8 年+ 沒有更新過。
圖片
顯然:IK 默認詞典覆蓋不了全部詞匯,尤其諸如“顯眼包”、“小米14”、“奧利給”、“葉氏那拉”等的新詞。如下截圖是我自定義的詞典的詞庫檢索截圖。
圖片
再來一波舉例看看:
PUT my_index_0512{ "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_smart", "fields": { "keyword": { "type": "keyword" } } } } }}
POST my_index_0512/_bulk{"index":{"_id":1}}{"title":"奧利給是一個網絡流行詞,第一次出現在一名快手主播直播時說的正能量語錄里。"}## 分詞為:“奧利” 和 “給” 兩個詞POST my_index_0512/_analyze{ "text":"奧利給是一個網絡流行詞,第一次出現在一名快手主播直播時說的正能量語錄里。", "analyzer":"ik_smart"}## 檢索不能召回結果,這里用 term 主要說明問題,合理性待商榷!POST my_index_0512/_search{ "profile": true, "query": { "term": { "title": "奧利給" } }}
圖片
結論:詞典決定分詞,詞典里沒有的詞,極大可能(有一定概率,比如:match_phrase 詞+詞組合的情況)檢索會檢索不到。
ps: 關于 term、match、match_phrase 區別等,推薦閱讀:檢索選型。
全文檢索的本質是查詢待檢索的關鍵詞在寫入所創建的索引中是否存在的過程。
存在,則召回;不存在,則返回空。
表面上可以看出,之前咱們2018年、2020年、2022年討論的方案用 match、match_phrase、match_phrase_prefix 等再結合 slop,貌似能解決一些問題,好像有些不召回的情況,可以召回了。
但,依然治標不治本。依然會存在一些“新詞”、“詞典里沒有的詞”等看似明明一段話里存在的詞,就是檢索不到的原因。
答案:不完全能!
但,可以嘗試空間換時間,借助 Ngram 能解決 99% 以上場景的問題。
針對讀者的問題,借助 Ngram 分詞實操一下:
### 3.1 創建索引DELETE new_spy_uat2PUT new_spy_uat2{ "settings": { "index.max_ngram_diff": 10, "analysis": { "analyzer": { "my_analyzer": { "tokenizer": "my_tokenizer", "char_filter": ["my_char_filter"] } }, "char_filter": { "my_char_filter": { "type": "pattern_replace", "pattern": "[^//p{L}//p{N}//s]+", "replacement": "" } }, "tokenizer": { "my_tokenizer": { "type": "ngram", "min_gram": 2, "max_gram": 10 } } } }, "mappings": { "properties": { "content": { "type": "text", "analyzer": "my_analyzer", "fields": { "keyword": { "type": "keyword" } } } } }}
在提供的 Elasticsearch 配置中,my_tokenizer 是一個基于 n-gram 的分詞器,配置了從最小 2 個字符到最大 10 個字符的 n-gram。
在《一本書講透 Elasticsearch》第6.4 章節 P111 解讀了自定義分詞器的三大核心組成:
咱們上面的“my_char_filter”定義了文本在分詞前進行預處理的字符過濾規則。實際是使用正則表達式刪除所有非字母、非數字、非空格字符,只保留字母、數字和空白字符,中文字符是可以保留的。
N-gram 是一種分詞方法,通過從文本中提取 n 個連續字符的滑動窗口來創建詞元(tokens)。這種方法在處理需要部分匹配和模糊搜索的應用中非常有用,比如搜索建議和拼寫錯誤的容錯處理。
在這種配置下,文本會被分解成所有可能的 2 到 10 個字符的組合。
例如,要執行如下檢索:
POST new_spy_uat2/_analyze{ "analyzer":"my_analyzer", "text":"奧利給這幾年才流行"}
分詞結果如下:
圖片
這種方法可以大大增加索引的大小因為每個詞都被分解成多個子詞,但同時也提高了搜索的靈活性和準確性,尤其是在搜索短文本或關鍵詞片段時。
這樣的分詞器尤其適合于搜索引擎的自動補全功能和處理用戶可能的輸入錯誤,因為它能夠在用戶輸入部分信息時就開始匹配相關的詞條。
POST new_spy_uat2/_bulk{ "index" : { "_index" : "new_spy_uat2", "_id" : "1" } }{ "content" : "新品豪車??限1000單食物鏈巴氏小仙包犬濕糧360g
本文鏈接:http://www.tebozhan.com/showinfo-26-88368-0.htmlElasticsearch 電商場景:明明有這個關鍵詞,但是搜不出來,怎么辦?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 一文徹底搞明白中介模式