Elasticsearch关键词高亮检索

bboss

1.准备工作

参考文档《集成Elasticsearch Restful API案例》导入和配置es客户端

2.创建索引表和初始化数据

通过组件DocumentCRUD 来创建索引表和初始化数据,DocumentCRUD 组件实现本文不做重点介绍:

  1. /**
  2. * 创建索引表,并导入高亮检索功能需要的测试数据
  3. */
  4. public void initIndiceAndData(){
  5. DocumentCRUD documentCRUD = new DocumentCRUD();
  6. documentCRUD.testCreateIndice();
  7. documentCRUD.testBulkAddDocuments();
  8. }

3.高亮检索功能实现

3.1 定义高亮检索dsl

在文件esmapper/demo.xml中增加testHighlightSearch配置:

  1. <!--
  2. 一个简单的检索dsl,中有四个变量
  3. name 全文检索字段
  4. startTime
  5. endTime
  6. 通过map传递变量参数值
  7. 变量语法参考文档:https://my.oschina.net/bboss/blog/1556866
  8. -->
  9. <property name="testHighlightSearch">
  10. <![CDATA[{
  11. "query": {
  12. "bool": {
  13. "filter": [
  14. { ## 时间范围检索,返回对应时间范围内的记录,接受long型的值
  15. "range": {
  16. "agentStarttime": {
  17. "gte": #[startTime],##统计开始时间
  18. "lt": #[endTime] ##统计截止时间
  19. }
  20. }
  21. }
  22. ],
  23. "must": [
  24. #*
  25. {
  26. "query_string": {
  27. "query": #[condition],
  28. "analyze_wildcard": true
  29. }
  30. }
  31. *#
  32. {
  33. ## 全文检索参考文档 https://www.elastic.co/guide/en/elasticsearch/reference/6.2/full-text-queries.html
  34. "match_phrase" : {
  35. "name" : {
  36. "query" : #[condition]
  37. }
  38. }
  39. }
  40. ]
  41. }
  42. },
  43. ## 最多返回1000条记录
  44. "size":1000,
  45. ## 高亮检索定义,参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-request-highlighting.html
  46. "highlight": {
  47. "pre_tags": [
  48. "<mark>"
  49. ],
  50. "post_tags": [
  51. "</mark>"
  52. ],
  53. "fields": {
  54. "*": {}
  55. },
  56. "fragment_size": 2147483647
  57. }
  58. }]]>
  59. </property>

3.2 编写高亮检索代码

创建检索类-org.bboss.elasticsearchtest.HighlightSearch

在其中定义以下方法

  1. public void highlightSearch() throws ParseException {
  2. //创建加载配置文件的客户端工具,用来检索文档,单实例多线程安全
  3. ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil(mappath);
  4. //设定查询条件,通过map传递变量参数值,key对于dsl中的变量名称
  5. //dsl中有三个变量
  6. // condition
  7. // startTime
  8. // endTime
  9. Map<String,Object> params = new HashMap<String,Object>();
  10. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  11. //设置时间范围,时间参数接受long值
  12. params.put("startTime",dateFormat.parse("2017-09-02 00:00:00"));
  13. params.put("endTime",new Date());
  14. params.put("condition","喜欢唱歌");//全文检索条件,匹配上的记录的字段值对应的匹配内容都会被高亮显示
  15. //执行查询,demo为索引表,_search为检索操作action
  16. ESDatas<Demo> esDatas = //ESDatas包含当前检索的记录集合,最多1000条记录,由dsl中的size属性指定
  17. clientUtil.searchList("demo/_search",//demo为索引表,_search为检索操作action
  18. "testHighlightSearch",//esmapper/demo.xml中定义的dsl语句
  19. params,//变量参数
  20. Demo.class);//返回的文档封装对象类型
  21. //获取总记录数
  22. long totalSize = esDatas.getTotalSize();
  23. System.out.println(totalSize);
  24. //获取结果对象列表,最多返回1000条记录
  25. List<Demo> demos = esDatas.getDatas();
  26. for(int i = 0; demos != null && i < demos.size(); i ++){//遍历检索结果列表
  27. Demo demo = demos.get(i);
  28. //记录中匹配上检索条件的所有字段的高亮内容
  29. Map<String,List<Object>> highLights = demo.getHighlight();
  30. Iterator<Map.Entry<String, List<Object>>> entries = highLights.entrySet().iterator();
  31. while(entries.hasNext()){
  32. Map.Entry<String, List<Object>> entry = entries.next();
  33. String fieldName = entry.getKey();
  34. System.out.print(fieldName+":");
  35. List<Object> fieldHighLightSegments = entry.getValue();
  36. for (Object highLightSegment:fieldHighLightSegments){
  37. /**
  38. * 在dsl中通过<mark></mark>来标识需要高亮显示的内容,然后传到web ui前端的时候,通过为mark元素添加css样式来设置高亮的颜色背景样式
  39. * 例如:
  40. * <style type="text/css">
  41. * .mark,mark{background-color:#f39c12;padding:.2em}
  42. * </style>
  43. */
  44. System.out.println(highLightSegment);
  45. }
  46. }
  47. }
  48. }

4.运行检索功能

定义junit测试用例:

  1. import org.junit.Test;
  2. import java.text.ParseException;
  3. public class HighlightSearchTest {
  4. @Test
  5. public void testHighlightSearch() throws ParseException {
  6. HighlightSearch highlightSearch = new HighlightSearch();
  7. highlightSearch.initIndiceAndData();
  8. highlightSearch.highlightSearch();
  9. }
  10. @Test
  11. public void testHighlightSearchOther() throws ParseException {
  12. HighlightSearch highlightSearch = new HighlightSearch();
  13. highlightSearch.initIndiceAndData();
  14. highlightSearch.highlightSearchOther();
  15. }
  16. }

在idea或者eclipse中运行测试用例即可,输出检索到的高亮内容信息如下:

  1. name:刘德华<mark>喜</mark><mark>欢</mark><mark>唱</mark><mark>歌</mark>454
  2. name:刘德华<mark>喜</mark><mark>欢</mark><mark>唱</mark><mark>歌</mark>488
  3. name:刘德华<mark>喜</mark><mark>欢</mark><mark>唱</mark><mark>歌</mark>508
  4. name:刘德华<mark>喜</mark><mark>欢</mark><mark>唱</mark><mark>歌</mark>518

5.完整的demo实例工程

https://github.com/bbossgroups/eshelloword-booter

https://gitee.com/bbossgroups/eshelloword-booter

6.参考文档

https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-request-highlighting.html

https://my.oschina.net/bboss/blog/1801273

7.开发交流

elasticsearch技术交流群:166471282

elasticsearch微信公众号:

bboss微信公众号:bbossgroups