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其他的一些知识,如果有需要可以翻阅查看,如果有哪些地方有问题,欢迎大家留言指正,感激不尽!



  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值