Elasticsearch实现复合查询,高亮结果等技巧

一.Es的配置

实现es的全文检索功能的第一步,首先从与es进行连接开始,这里我使用的是es的5.x java api语法.


 
 
  1. public TransportClient esClient() throws UnknownHostException{
  2. Settings settings = Settings.builder()
  3. .put( "cluster.name", "my-application") //节点的名字
  4. .put( "client.transport.sniff", true)
  5. .build();
  6. InetSocketTransportAddress iAddress = new InetSocketTransportAddress( //连接es的ip地址和端口号
  7. InetAddress.getByName( "127.0.0.1"), 9300
  8. );
  9. //根据先前的配置生成client,后面的操作基本都是基于这个
  10. TransportClient client = new PreBuiltTransportClient(settings)
  11. .addTransportAddress(iAddress);
  12. return client;
  13. }

 

二.功能的实现

以下是全文检索的核心代码,包括我遇到的错误以及解决,包括如何对高亮失效,高亮不全等的解决.

1.查询条件


 
 
  1. TransportClient esClient = esClient(); //获取先前生成的client
  2. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); //生成复合查询构造器
  3. boolQuery.mustNot(
  4. QueryBuilders.matchQuery( "",) //字段必须不包含啥
  5. );
  6. boolQuery.should(
  7. QueryBuilders.matchQuery(, ) //字段可以包含啥,相当于或者
  8. );
  9. boolQuery.must(
  10. QueryBuilders.matchQuery(,) //字段必须包含啥
  11. );

2.高亮条件


 
 
  1. //配置标题高亮显示
  2. HighlightBuilder highlightBuilder = new HighlightBuilder(); //生成高亮查询器
  3. highlightBuilder.field(title); //高亮查询字段
  4. highlightBuilder.field(content); //高亮查询字段
  5. highlightBuilder.requireFieldMatch( false); //如果要多个字段高亮,这项要为false
  6. highlightBuilder.preTags( "<span style=\"color:red\">"); //高亮设置
  7. highlightBuilder.postTags( "</span>");
  8. //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
  9. highlightBuilder.fragmentSize( 800000); //最大高亮分片数
  10. highlightBuilder.numOfFragments( 0); //从第一个分片获取高亮片段

3.查询配置


 
 
  1. // 根据字段进行排序,这里我根据时间进行倒排
  2. FieldSortBuilder timeSort = SortBuilders.fieldSort( "time").order(SortOrder.DESC);
  3. //查询请求生成
  4. SearchRequestBuilder requestBuilder = esClient.prepareSearch(indexname) //索引名字
  5. .setTypes(indextype) //索引类型
  6. .setQuery(boolQuery) //配置查询条件
  7. .addSort( new ScoreSortBuilder()) //根据查询相关度进行排序
  8. .addSort(timeSort) //再根据时间进行排序
  9. .setTrackScores( true) //避免分页之后相关性乱了
  10. .highlighter(highlightBuilder) //配置高亮
  11. .setFrom( from) //设置分页
  12. .setSize();

 

4.获取查询结果对其高亮


 
 
  1. //获取查询结果
  2. SearchResponse searchResponse = requestBuilder.get();
  3. List<Map<String, Object>> course = new ArrayList<>();
  4. if(searchResponse.status() != RestStatus.OK){
  5. return course;
  6. }
  7. for(SearchHit hit:searchResponse.getHits()){
  8. //获取高亮字段
  9. Map<String, HighlightField> highlightFields = hit.getHighlightFields();
  10. HighlightField titleField = highlightFields.get( "");
  11. HighlightField contentField = highlightFields.get( "");
  12. Map<String, Object> source = hit.getSource();
  13. //千万记得要记得判断是不是为空,不然你匹配的第一个结果没有高亮内容,那么就会报空指针异常,这个错误一开始真的搞了很久
  14. if(titleField!= null){
  15. Text[] fragments = titleField.fragments();
  16. String name = "";
  17. for (Text text : fragments) {
  18. name+=text;
  19. }
  20. source.put( "", name); //高亮字段替换掉原本的内容
  21. }
  22. course.add(source);
  23. }
  24. esClient.close(); //用完记得关闭
  25. return course;

 

三.结语

这样前端所获取结果的搜索内容将会被<span style="color:red;"></span>所包含,比如我前端是微信小程序,所以直接获取内容进行渲染的话,就是一堆字符串,所以用的是小程序的富文本标签<rich-text>.

如果你觉得文章内容对你有用的话,不用忘记评论,点赞.


版权声明:本文为qq_44813090原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。