1. 程式人生 > >elasticsearch5.5.2用javaAPI實現搜尋結果高亮顯示和搜尋建議

elasticsearch5.5.2用javaAPI實現搜尋結果高亮顯示和搜尋建議

前言:

像百度、360搜尋等等,我們輸入完搜尋條件時,他會自動出來一個提示框,將我們輸入的關鍵詞進行自動補全,即搜尋推薦。當我們點選搜尋後,返回的搜尋結果中會將我們搜尋的內容進行高亮的顯示(不同顏色標記出來),強大的elasticsearch就提供了這些功能。在這裡我會使用javaAPI來介紹一下搜尋結果Highlight高亮顯示和completion suggest搜尋推薦的具體實現,方便以後進行查閱。

原始碼下載

一、準備開發環境

該專案基於springboot

1.1jdk1.8

1.2elasticsearch需要用到的maven依賴

<!--es-->
		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>transport</artifactId>
			<version>${elasticsearch.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.7</version>
		</dependency>
1.3elasticsearch的client進行配置,當我們需要用到client的時候直接注入就可以了
@Configuration
public class MyConfig {

    @Bean
    public TransportClient client() throws UnknownHostException{
        //配置節點
        InetSocketTransportAddress node = new InetSocketTransportAddress(
                InetAddress.getByName("localhost"),
                9300
        );
        //配置settiong
        Settings settings = Settings.builder()
                .put("cluster.name", "my-application")
                .build();

        TransportClient client = new PreBuiltTransportClient(settings);
        client.addTransportAddress(node);

        return client;
    }
}

二、搜尋結果高亮顯示

2.1java程式碼實現Highlight高亮顯示

下邊的程式碼中,涉及了專案中分頁的一些程式碼,如果沒有需求直接進行刪除就可以了。

 /**
     * 進行搜尋
     * 將結果進行分頁
     * @param title
     * @return
     */
    @RequestMapping("searchItems")
    @ResponseBody
    public Map<String,Object> goSearch(
            @RequestParam(value="title",defaultValue = "") String title,
            @RequestParam(value="pageNow",defaultValue = "") String PageNow,
            @RequestParam(value="totalCount",defaultValue = "") String totalCount
    ){
        //返回的map,進行資料封裝
        Map<String,Object> msgMap = new HashMap<String,Object>();
        //建立bool查詢,如果沒有組合查詢,直接寫QueryBuilder
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
        //使用should實現或者查詢
        boolBuilder.must(QueryBuilders.matchQuery("title",title));
        //查詢總記錄數和當前頁數
        long pageSize = 0;
        if(totalCount != "" && totalCount != null){
            pageSize = new Long(totalCount);
        }
        long pn = 0;
        if(PageNow != "" && PageNow != null){
            pn = new Long(PageNow);
        }
        Page page = new Page(pageSize,pn);
        //c查詢
        SearchRequestBuilder searchRequestBuilder = this.client.prepareSearch("testshop")
                .setTypes("item")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) //設定查詢型別:1.SearchType.DFS_QUERY_THEN_FETCH 精確查詢; 2.SearchType.SCAN 掃描查詢,無序
                .setQuery(boolBuilder)
                .setFrom(new Long(page.getStartPos()).intValue())
                .setSize(10);

        //設定高亮顯示
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);
        highlightBuilder.preTags("<span style=\"color:red\">");
        highlightBuilder.postTags("</span>");
        searchRequestBuilder.highlighter(highlightBuilder);
        //執行結果
        SearchResponse response = searchRequestBuilder.get();
        //接受結果
        List<Map<String,Object>> result = new ArrayList<>();
        //遍歷結果
        for(SearchHit hit:response.getHits()){
            Map<String, Object> source = hit.getSource();
            //處理高亮片段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField nameField = highlightFields.get("title");
            if(nameField!=null){
                Text[] fragments = nameField.fragments();
                String nameTmp ="";
                for(Text text:fragments){
                    nameTmp+=text;
                }
                //將高亮片段組裝到結果中去
                source.put("title",nameTmp);
            }
            result.add(source);
        }
        //封裝資料返回
        msgMap.put("itemsList",result);     //搜尋結果
        //msgMap.put("page","page");          //分頁
        msgMap.put("took",response.getTook().getSecondsFrac()); //獲取響應需要的時間
        msgMap.put("total",totalCount);     //獲得查詢的總記錄數
        return msgMap;
    }

2.2效果展示

實現以下樣式,上邊的程式碼是關鍵,還需要自己寫一下前臺的js,如果需要原始碼可以給我留言


三、搜尋建議,搜尋關鍵字自動補充

3.1.建立mapping

如果完成搜尋建議,需要在mapping中先設定completion

PUT /news_website
{
  "mappings": {
    "news" : {
      "properties" : {
        "title" : {
          "type": "text",
          "analyzer": "ik_max_word",
          "fields": {
            "suggest" : {
              "type" : "completion",
              "analyzer": "ik_max_word"
            }
          }
        },
        "content": {
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

使用bulk批量插入一些資料,方便我們進行測試

 @RequestMapping("bulk")
	 @ResponseBody
	 public String insetDate() throws Exception{
		 BulkRequestBuilder bulkRequest = client.prepareBulk();
		 //插入
		 bulkRequest.add(this.client.prepareIndex("news_website", "news", "1")
		         .setSource(XContentFactory.jsonBuilder()
		                     .startObject()
		                         .field("title","大話西遊電影")
		                         .field("content","大話西遊的電影時隔20年即將在2017年4月重映")
		                     .endObject()
		                   )
		         ); 
		 bulkRequest.add(this.client.prepareIndex("news_website", "news", "2")
		         .setSource(XContentFactory.jsonBuilder()
		                     .startObject()
		                         .field("title","大話西遊小說")
		                         .field("content","某知名網路小說作家已經完成了大話西遊同名小說的出版")
		                     .endObject()
		                   )
		         ); 
		 bulkRequest.add(this.client.prepareIndex("news_website", "news", "3")
		         .setSource(XContentFactory.jsonBuilder()
		                     .startObject()
		                         .field("title","大話西遊手遊")
		                         .field("content","網易遊戲近日出品了大話西遊經典IP的手遊,正在火爆內測中")
		                     .endObject()
		                   )
		         ); 
		 //批量執行
		 BulkResponse bulkResponse = bulkRequest.get();
		 //client.close();
		 return bulkResponse.getTook().toString();
	 }
3.2javaAPI實現completion suggest搜尋推薦

下邊的程式碼是我專案中的一部分程式碼,我直接將他搬了過來

  /**
     * 搜尋建議
     * @param tmptitle
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("suggestion")
    @ResponseBody
    public Map<String,Object> querySuggestion(
            @RequestParam(value="tmptitle",defaultValue = "") String tmptitle
    ) throws UnsupportedEncodingException {

        //返回的map,進行資料封裝
        Map<String,Object> msgMap = new HashMap<String,Object>();
        //建立需要搜尋的inde和type
        SearchRequestBuilder requestBuilder = client.prepareSearch("news_website").setTypes("news");
        //設定搜尋建議
        CompletionSuggestionBuilder completionSuggestionBuilder = new CompletionSuggestionBuilder("title.suggest")
                .prefix(tmptitle).size(10);
        SuggestBuilder suggestBuilder = new SuggestBuilder().addSuggestion("title.suggest", completionSuggestionBuilder);

        requestBuilder.suggest(suggestBuilder);
        //進行搜尋
        SearchResponse suggestResponse = requestBuilder.execute().actionGet();

        //用來處理的接受結果
        List<String> result = new ArrayList<>();

        List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries = suggestResponse.getSuggest()
                .getSuggestion("title.suggest").getEntries();
        //處理結果
        for(Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> op:entries){
            List<? extends Option> options = op.getOptions();
            for(Suggest.Suggestion.Entry.Option pp : options){
                result.add(pp.getText().toString());
            }
        }
        msgMap.put("result",result);
        return msgMap;
    }
3.3檢視效果

目前還沒有將他整合到頁面搜尋框中,只是實現了功能,當我們輸入 “大話”後,他會自動補全:“大話西遊電影”,“大話西遊手遊”,“大話西遊小說”。


以上就是對elasticsearch5.5.2版本的高亮顯示和搜尋建議的java實現,我的其他文章也講到了elasticsearch其他的一些知識,如果有需要可以翻閱檢視,如果有哪些地方有問題,歡迎大家留言指正,感激不盡!