1. 程式人生 > >ES[7.6.x]學習筆記(十二)高亮 和 搜尋建議

ES[7.6.x]學習筆記(十二)高亮 和 搜尋建議

ES當中大部分的內容都已經學習完了,今天呢算是對前面內容的查漏補缺,把ES中非常實用的功能整理一下,在以後的專案開發中,這些功能肯定是對你的專案加分的,我們來看看吧。 ## 高亮 高亮在搜尋功能中是十分重要的,我們希望搜尋的內容在搜尋結果中重點突出,讓使用者聚焦在搜尋的內容上。我們看看在ES當中是怎麼實現高亮的,我們還用之前的索引`ik_index`,前面的章節,我們搜尋過`香蕉好吃`,但是返回的結果中並沒有高亮,那麼想要在搜尋結果中,對`香蕉好吃`高亮該怎麼辦呢?我們看看, ```shell POST /ik_index/_search { "query": { "bool": { "must": { "match": { "desc": "香蕉好吃" } } } }, "highlight": { "fields": { "desc": {} } } } ``` 我們重點看一下請求體中的`highlight`部分,這部分就是對返回結果高亮的設定,`fields`欄位中,指定哪些欄位需要高亮,我們指定了`desc`欄位,執行一下,看看結果吧。 ```json { "took": 73, "timed_out": false, "_shards": { "total": 1,"successful": 1,"skipped": 0,"failed": 0}, "hits": { "total": { "value": 5, "relation": "eq" }, "max_score": 1.3948275, "hits": [ { "_index": "ik_index", "_type": "_doc", "_id": "2", "_score": 1.3948275, "_source": { "id": 1, "title": "香蕉", "desc": "香蕉真好吃" }, "highlight": { "desc": [ "香蕉好吃" ] } } …… ``` 我們看到在返回的結果中,增加了`highlight`,`highlight`裡有我們指定的高亮欄位`desc`,它的值是`香蕉好吃`,其中“香蕉”和“好吃”欄位在``標籤中,前端的小夥伴就可以針對這個``標籤寫樣式了。我們再看看程式當中怎麼設定高亮,繼續使用上一節中的搜尋的程式, ```java public void searchIndex() throws IOException { SearchRequest searchRequest = new SearchRequest("ik_index"); SearchSourceBuilder ssb = new SearchSourceBuilder(); QueryBuilder qb = new MatchQueryBuilder("desc","香蕉好吃"); ssb.query(qb); HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("desc"); ssb.highlighter(highlightBuilder); searchRequest.source(ssb); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] hits = response.getHits().getHits(); for (SearchHit hit : hits) { String record = hit.getSourceAsString(); HighlightField highlightField = hit.getHighlightFields().get("desc"); for (Text fragment : highlightField.getFragments()) { System.out.println(fragment.string()); } } } ``` 我們重點關注一下`HighlightBuilder`,我們在傳送請求前,建立`HighlightBuilder`,並指定高亮欄位為`desc`。搜尋結束後,我們取結果,從`hit`當中取出高亮欄位`desc`,然後打印出`fragment`,執行一下,看看結果吧, ```shell 香蕉
好吃 香蕉好吃 橘子真好吃 桃子真好吃 蘋果真好吃 ``` 完全符合預期,“香蕉好吃”被分詞後,在搜尋結果中都增加了``標籤,我們可不可以自定義高亮標籤呢?當然是可以的,我們稍微改一下程式就可以了, ```java HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("desc"); highlightBuilder.preTags(""); highlightBuilder.postTags(""); ssb.highlighter(highlightBuilder); ``` 在`HighlightBuilder`中,使用`preTags`新增起始標籤,指定為``,用`postTags`新增閉合標籤,指定為`
`,再執行一下,看看結果, ```shell 香蕉好吃 香蕉好吃 橘子真好吃 桃子真好吃 蘋果真好吃 ``` 結果完全正確,用``替換了``,是不是很靈活。接下來我們再看看搜尋建議。 ## 搜尋建議 “搜尋建議”這個功能也是相當實用的,當我們在搜尋框中輸入某個字時,與這個字的相關搜尋內容就會羅列在下面,我們選擇其中一個搜尋就可以了,省去了敲其他字的時間。我們看看ES中是怎麼實現“搜尋建議”的。 如果要在ES中使用“搜尋建議”功能,是需要特殊設定的,要設定一個型別為`completion`的欄位,由於之前的索引中已經有了資料,再新增欄位是會報錯的,索引我們新建一個索引, ```json PUT /my_suggester { "settings":{ "analysis":{ "analyzer":{ "default":{ "type":"ik_max_word" } } } }, "mappings":{ "dynamic_date_formats": [ "MM/dd/yyyy", "yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" ], "properties":{ "suggest":{ "type":"completion" } } } } ``` 這已經成了我們新建索引的一個標配了,指定分詞器為ik中文分詞,動態欄位的時間對映格式,以及搜尋建議欄位,注意`suggest`欄位的型別為`completion`。我們再新增欄位的時候,就要為`suggest`欄位新增值了,如下: ```shell POST /my_suggester/_doc { "title":"天氣", "desc":"今天天氣不錯", "suggest": { "input": "天氣" } } POST /my_suggester/_doc { "title":"天空", "desc":"藍藍的天空,白白的雲", "suggest": { "input": "天空" } } ``` 我們向索引中添加了兩條資料,大家需要額外注意的是`suggest`欄位的賦值方法,要使用`input`,我們看一下資料, ![](https://img2020.cnblogs.com/blog/1191201/202005/1191201-20200528152152273-510358324.png) `suggest`欄位並沒有像其他欄位那樣展示出來,說明它和其他欄位是不一樣的。現在我們如果只輸入一個“天”字,看看搜尋建議能不能給出提示,如下: ```shell POST /my_suggester/_search { "suggest": { "s-test": { "prefix": "天", "completion": { "field": "suggest" } } } } ``` 在請求體中,`suggest`就是“搜尋建議”的標識,`s-test`是自定義的一個名稱,`prefix`是字首,也就是我們輸入的“天”字,`completion`指定搜尋建議的欄位,我們看看查詢的結果, ```json …… "suggest": { "s-test": [ { "text": "天", "offset": 0, "length": 1, "options": [{ "text": "天氣", "_index": "my_suggester", "_type": "_doc", "_id": "QtgAWnIBOZNtuLQtJgpt", "_score": 1, "_source": { "title": "天氣","desc": "今天天氣不錯","suggest": { "input": "天氣"}} } , { "text": "天空", "_index": "my_suggester", "_type": "_doc", "_id": "T9gAWnIBOZNtuLQtWQoX", "_score": 1, "_source": { "title": "天空","desc": "藍藍的天空,白白的雲","suggest": { "input": "天空"}} } ] } ] } ``` 在`s-test.options`裡,包含了兩條記錄,`text`欄位就是我們寫的建議欄位,後面`_source`裡還包含對應的資料,下面我們再看看程式裡怎麼使用“搜尋建議”, ```java public void searchSuggest(String prefix) throws IOException { SearchRequest searchRequest = new SearchRequest("my_suggester"); SearchSourceBuilder ssb = new SearchSourceBuilder(); CompletionSuggestionBuilder suggest = SuggestBuilders .completionSuggestion("suggest") .prefix(prefix); SuggestBuilder suggestBuilder = new SuggestBuilder(); suggestBuilder.addSuggestion("s-test",suggest); ssb.suggest(suggestBuilder); searchRequest.source(ssb); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); CompletionSuggestion suggestion = response.getSuggest().getSuggestion("s-test"); for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) { System.out.println(option.getText().string()); } } @Test public void searchSuggest() throws IOException { eService.searchSuggest("天"); } ``` 我們建立了`CompletionSuggestionBuilder`,通過方法`completionSuggestion`指定“搜尋建議”欄位`suggest`,並且指定字首為方法傳入的`prefix`,我們在測試的時候傳入"天"字。然後,我們自定義“搜尋建議”的名字為`s-test`,傳入前面構造好的`suggest`。 傳送請求後,在響應中獲取前面自定義的`s-test`,然後迴圈`options`,取出`text`欄位,這就是搜尋建議的欄位,我們執行一下,看看結果, ```shell 天氣 天空 ``` 完全符合預期,這樣使用者在搜尋的時候,就會給出提示資訊了。 好了,今天這兩個ES的知識點就全部OK了~ 大家有問題在評論區留言。