elasticsearch搜素关键字自动补全(suggest)
生活随笔
收集整理的這篇文章主要介紹了
elasticsearch搜素关键字自动补全(suggest)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
elasticsearch搜素關鍵字自動補全顧名思義 在搜索框搜索時能有提示列表可供選擇。
最終效果如下:
該搜索優化功能是elasticsearch自帶的即suggest,suggest即存儲一個詞庫,每次搜索發送請求去詞庫中檢索,匹配到即返回。
接下來我們一步一步實現上述功能。
1.建立索引
我這預先準備了一個房屋信息的索引house
{"settings": {"number_of_replicas": 0},"mappings": {"house": {"dynamic": false,"properties": {"houseId": {"type": "long"},"title": {"type": "text","index": "analyzed","analyzer": "ik_smart","search_analyzer": "ik_smart"},"price": {"type": "integer"},"area": {"type": "integer"},"createTime": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"lastUpdateTime": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"cityEnName": {"type": "keyword"},"regionEnName": {"type": "keyword"},"direction": {"type": "integer"},"distanceToSubway": {"type": "integer"},"subwayLineName": {"type": "keyword"},"subwayStationName": {"type": "keyword"},"tags": {"type": "text"},"street": {"type": "keyword"},"district": {"type": "keyword"},"description": {"type": "text","index": "analyzed","analyzer": "ik_smart","search_analyzer": "ik_smart"},"layoutDesc": {"type": "text","index": "analyzed","analyzer": "ik_smart","search_analyzer": "ik_smart"},"traffic": {"type": "text","index": "analyzed","analyzer": "ik_smart","search_analyzer": "ik_smart"},"roundService": {"type": "text","index": "analyzed","analyzer": "ik_smart","search_analyzer": "ik_smart"},"rentWay": {"type": "integer"},"suggest": {"type": "completion"},"room": {"type": "integer"}}}} }注意關鍵字段suggest,type為completion
2.向建好的索引中添加數據
主要注意suggest字段中如何添加數據
private boolean updateSuggest(HouseIndexTemplate indexTemplate) {//將分詞字段加入AnalyzeRequestBuilder,通過ik_smart分詞后會生成多個詞組,然后將詞組加入suggest字段AnalyzeRequestBuilder requestBuilder = new AnalyzeRequestBuilder(this.esClient, AnalyzeAction.INSTANCE, INDEX_NAME, indexTemplate.getTitle(),indexTemplate.getLayoutDesc(), indexTemplate.getRoundService(),indexTemplate.getDescription(), indexTemplate.getSubwayLineName(),indexTemplate.getSubwayStationName());//采用ik_smart分詞requestBuilder.setAnalyzer("ik_smart");AnalyzeResponse response = requestBuilder.get();List<AnalyzeResponse.AnalyzeToken> tokens = response.getTokens();if (tokens == null) {logger.warn("Can not analyze token for house: " + indexTemplate.getHouseId());return false;}List<HouseSuggest> suggests = new ArrayList<>();for (AnalyzeResponse.AnalyzeToken token : tokens) {// 排序數字類型 & 小于2個字符的分詞結果if ("<NUM>".equals(token.getType()) || token.getTerm().length() < 2) {continue;}HouseSuggest suggest = new HouseSuggest();suggest.setInput(token.getTerm());suggests.add(suggest);}// 定制化小區自動補全(不需要分詞的字段手動額外加入)HouseSuggest suggest = new HouseSuggest();suggest.setInput(indexTemplate.getDistrict());suggests.add(suggest);indexTemplate.setSuggest(suggests);return true;}如上代碼表示:
首先將title、layoutDesc、roundService、description、subwayLineName、subwayStationName通過ik_smart分詞后,將分詞后的字詞加入suggests 集合;
然后將不需要分詞的字段district手動加入suggests集合;
其中HouseIndexTemplate 只是一個索引對象,里面封裝了索引所需字段,注意其中suggest為 集合:
private List<HouseSuggest> suggest;最后將HouseIndexTemplate對象寫入elasticsearch中即可。
IndexResponse response = this.esClient.prepareIndex(INDEX_NAME, INDEX_TYPE).setSource(objectMapper.writeValueAsBytes(indexTemplate), XContentType.JSON).get();寫入后結構如下 :
3.開始做檢索
前端js調用檢索接口
$('#keyword-box').autocomplete({minLength: 2, // 最小字符數,默認1delay: 300, // 延遲加載300mssource: function (request, response) { // 數據源$.ajax({url: '/rent/house/autocomplete?prefix=' + request.term,success: function (res) {if (res.code === 200) {response(res.data);}}});},select: function (event, ui) { // 選中事件$('#keyword-box').text(ui.item.value);window.location.href = locate_url(start, size);}});后端接口和服務層:
controller:
/*** 自動補全接口*/@GetMapping("rent/house/autocomplete")@ResponseBodypublic ApiResponse autocomplete(@RequestParam(value = "prefix") String prefix) {if (prefix.isEmpty()) {return ApiResponse.ofStatus(ApiResponse.Status.BAD_REQUEST);}ServiceResult<List<String>> result = this.searchService.suggest(prefix);return ApiResponse.ofSuccess(result.getResult());}service:
@Overridepublic ServiceResult<List<String>> suggest(String prefix) {CompletionSuggestionBuilder suggestion = SuggestBuilders.completionSuggestion("suggest").prefix(prefix).size(5);SuggestBuilder suggestBuilder = new SuggestBuilder();suggestBuilder.addSuggestion("autocomplete", suggestion);SearchRequestBuilder requestBuilder = this.esClient.prepareSearch(INDEX_NAME).setTypes(INDEX_TYPE).suggest(suggestBuilder);logger.debug(requestBuilder.toString());SearchResponse response = requestBuilder.get();Suggest suggest = response.getSuggest();if (suggest == null) {return ServiceResult.of(new ArrayList<>());}Suggest.Suggestion result = suggest.getSuggestion("autocomplete");int maxSuggest = 0;Set<String> suggestSet = new HashSet<>();for (Object term : result.getEntries()) {if (term instanceof CompletionSuggestion.Entry) {CompletionSuggestion.Entry item = (CompletionSuggestion.Entry) term;if (item.getOptions().isEmpty()) {continue;}for (CompletionSuggestion.Entry.Option option : item.getOptions()) {String tip = option.getText().string();if (suggestSet.contains(tip)) {continue;}suggestSet.add(tip);maxSuggest++;}}if (maxSuggest > 5) {break;}}List<String> suggests = Lists.newArrayList(suggestSet.toArray(new String[]{}));return ServiceResult.of(suggests);}?
總結
以上是生活随笔為你收集整理的elasticsearch搜素关键字自动补全(suggest)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对标行业万元高端标准!小米米家智能零冷热
- 下一篇: elasticsearch索引结构和配置