[Java]-Elastic中suggest查询建议
文章目錄
- 查詢建議API
- 單個建議查詢詞
- 多個建議查詢詞
- Suggester
- Term suggester
- 參數
- phrase suggester
- completion suggester
- 搜索框實現
查詢建議(suggest)是為用戶提供良好的使用體驗。主要包括: 拼寫檢查; 自動建議查詢詞(自動補全)。
官方文檔:https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-suggesters.html#。
查詢建議API
查詢建議也是使用_search端點地址。在DSL中suggest節點來定義需要的建議查詢。
單個建議查詢詞
POST _search {"query" : {"match": {"message": "tring out Elasticsearch"}},"suggest" : { <!-- 定義建議查詢 -->"my-suggestion" : { <!-- 一個建議查詢名 -->"text" : "tring out Elasticsearch", <!-- 查詢文本 -->"term" : { <!-- 使用詞項建議器 -->"field" : "message" <!-- 指定在哪個字段上獲取建議詞 -->}}} }多個建議查詢詞
可以多個建議詞一起查詢:
POST _search {"suggest": {"my-suggest-1" : {"text" : "tring out Elasticsearch","term" : {"suggest_mode": "missing", "field" : "message"}},"my-suggest-2" : {"text" : "kmichy","term" : {"field" : "user"}}} }也可以多個查詢使用同一個查詢文本:
POST _search {"suggest": {"text" : "tring out Elasticsearch","my-suggest-1" : {"term" : {"field" : "message"}},"my-suggest-2" : {"term" : {"field" : "user"}}} }Suggester
Suggesters基本的運作原理是將輸入的文本分解為token,然后在索引的字典里查找相似的term并返回。 根據使用場景的不同,Elasticsearch里設計了4種類別的Suggester,分別是:
- Term Suggester
- Phrase Suggester
- Completion Suggester
- Context Suggester
Term suggester
對輸入的文本進行分詞,為每個詞進行模糊匹配查詢提供詞項建議。對于在索引中存在詞默認不提供建議詞,不存在的詞則根據模糊查詢結果進行排序后取一定數量的建議詞。
| text | 輸入文本(用戶的輸入),根據此文本查找建議 |
| field | 要查詢的字段 |
| analyzer | 指定分詞器 |
| size | 每個詞返回的最大建議詞數量 |
| sort | 建議詞的排序方式: 1. score:先按評分排序,再按文檔頻率、term順序排; 2. frequency:先按文檔頻率排序,再按評分、term順序排 |
| suggest_mode | 建議模式(控制提供建議詞的方式): 1. missing:默認方式,僅在‘要搜索詞項’不在索引中存在時,才提供建議詞; 2. popular:僅提供頻率比‘要搜索詞項’高的建議詞; 3. always:總是提供建議詞; |
參數
| max_edits | 表示被選為建議的edit distance的最大值,只能是1,2之間的數(可以是小數),默認是2 |
| prefix_length | 表示被選為建議的最小前綴字符的長度,默認為1,增加這個長度可以提高拼寫檢查的性能,通常拼寫錯誤不會發生在術語的最前面 |
| min_word_length | 表示推薦文本的最小長度,默認為4 |
| shard_size | 設置從每個分片檢索的建議的最大數量。在reduce階段,根據size選項只返回前N個建議。默認是和size選項一樣 |
| max_inspections | 表示一個因子,這個參數和shard_size參數相乘以便在分片級別檢查更多的候選者的拼寫錯誤,參數默認為5 |
| min_doc_freq | 表示一個建議中應包含文檔數目的最小限制,可以指定為一個確切的數或文檔數的相對百分比,默認是0(即不開啟此功能) |
| max_term_freq | 表示推薦文本可以包含的文檔數目的最大限制,可以是一個代表文檔頻率的確切值,也可以是一個相對百分數(比如0.4),默認是0.01f。這個參數可以用來排除高頻術語的拼寫檢查 |
| string_distance | 表示一個字符串距離用于和推薦內容相比它們之間的相似性,這個參數可能的值有5個: internal:表示默認的基于damerau_levenshtein算法,但在比較字符串距離內的索引已經做過高度優化 damerau_levenshtein:是一種基于Damerau-Levenshtein算法的字符串距離算法 levenshtein:是一種基于Levenshtein edit distance算法的字符串距離算法 jaro_winkler:是一種基于Jaro-Winkler算法的字符串距離算法 ngram:是一種基于字符連詞的字符串距離算法 |
phrase suggester
短語建議,在term的基礎上,考量多個term間的關系(是否同時出現在索引的原文里,相鄰程度,以及詞頻等):
public void phraseSuggestSearch(String index, String field, String keyword) {try (RestHighLevelClient rhlClient = ESClient.getClient()) {PhraseSuggestionBuilder phraseSuggestion = SuggestBuilders.phraseSuggestion(field);phraseSuggestion.text(keyword);phraseSuggestion.size(5);SuggestBuilder suggestBuilder = new SuggestBuilder();String suggestName = "sugName";suggestBuilder.addSuggestion(suggestName, phraseSuggestion);SearchRequest searchRequest = new SearchRequest(index);SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.suggest(suggestBuilder);searchRequest.source(sourceBuilder);SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();if (suggest != null) {Suggest.Suggestion result = suggest.getSuggestion(suggestName);for (Object term : result.getEntries()) {if(term instanceof PhraseSuggestion.Entry) {PhraseSuggestion.Entry entry = (PhraseSuggestion.Entry)term;entry.getOptions().forEach(z->{System.out.println("Text: " + z.getText() + ", score: " + z.getScore());});}else {System.out.println("It is not phraseSuggestion.Entry: " + term);}}}} catch (Exception ex) {System.out.println(index + " query fail: " + ex);} }completion suggester
Completion Suggester提供自動完成/隨類型搜索的功能;這是一種導航特性,可以在用戶鍵入時引導他們找到相關結果,提高搜索精度。因此實現上它和前面兩個Suggester采用了不同的數據結構,索引并非通過倒排來完成,而是將analyze過的數據編碼成FST和索引一起存放。對于一個open狀態的索引,FST會被ES整個裝載到內存里的,進行前綴查找速度極快。但是FST只能用于前綴查找,這也是Completion Suggester的局限所在。
為了使用自動補全,索引中用來提供補全建議的字段需特殊設計,字段類型為 completion。
搜索框實現
要實現搜索框的補全/糾錯功能:
- 在用戶剛開始輸入的過程中,使用Completion Suggester進行關鍵詞前綴匹配,剛開始匹配項會比較多,隨著用戶輸入字符增多,匹配項越來越少。
- 如果用戶輸入比較精準,可能Completion Suggester的結果已經夠好,用戶已經可以看到理想的備選項了。 如果Completion Suggester已經到了零匹配,那么可以猜測是否用戶有輸入錯誤,這時候可以嘗試一下Phrase Suggester。如果Phrase Suggester沒有找到任何option,開始嘗試term Suggester。
- 精準程度上(Precision)看: Completion > Phrase > term, 而召回率上(Recall)則反之。從性能上看,Completion Suggester是最快的,如果能滿足業務需求,只用Completion Suggester做前綴匹配是最理想的。Phrase和Term由于是做倒排索引的搜索,相比較而言性能應該要低不少,應盡量控制suggester用到的索引的數據量,最理想的狀況是經過一定時間預熱后,索引可以全量map到內存。
總結
以上是生活随笔為你收集整理的[Java]-Elastic中suggest查询建议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: es 搜索推荐:Suggest
- 下一篇: 压缩大战真相