ES[7.6.x]学习笔记(十二)高亮 和 搜索建议

Wesley13
• 阅读 755

ES当中大部分的内容都已经学习完了,今天呢算是对前面内容的查漏补缺,把ES中非常实用的功能整理一下,在以后的项目开发中,这些功能肯定是对你的项目加分的,我们来看看吧。

高亮

高亮在搜索功能中是十分重要的,我们希望搜索的内容在搜索结果中重点突出,让用户聚焦在搜索的内容上。我们看看在ES当中是怎么实现高亮的,我们还用之前的索引ik_index,前面的章节,我们搜索过香蕉好吃,但是返回的结果中并没有高亮,那么想要在搜索结果中,对香蕉好吃高亮该怎么办呢?我们看看,

POST /ik_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "desc": "香蕉好吃"
        }
      }
    }
  },
  "highlight": {
    "fields": {
      "desc": {}
    }
  }
}

我们重点看一下请求体中的highlight部分,这部分就是对返回结果高亮的设置,fields字段中,指定哪些字段需要高亮,我们指定了desc字段,执行一下,看看结果吧。

{
    "took": 73,
    "timed_out": false,
    "_shards": { "total": 1,"successful": 1,"skipped": 0,"failed": 0},
    "hits": {
        "total": {
            "value": 5,
            "relation": "eq"
        },
        "max_score": 1.3948275,
        "hits": [
            {
            "_index": "ik_index",
            "_type": "_doc",
            "_id": "2",
            "_score": 1.3948275,
            "_source": {
                "id": 1,
                "title": "香蕉",
                "desc": "香蕉真好吃"
                },
            "highlight": {
                "desc": [
                        "<em>香蕉</em>真<em>好吃</em>"
                    ]
                }
            }
        ……

我们看到在返回的结果中,增加了highlighthighlight里有我们指定的高亮字段desc,它的值是<em>香蕉</em>真<em>好吃</em>,其中“香蕉”和“好吃”字段在<em>标签中,前端的小伙伴就可以针对这个<em>标签写样式了。我们再看看程序当中怎么设置高亮,继续使用上一节中的搜索的程序,

    public void searchIndex() throws IOException {
        SearchRequest searchRequest = new SearchRequest("ik_index");
        SearchSourceBuilder ssb = new SearchSourceBuilder();
        QueryBuilder qb = new MatchQueryBuilder("desc","香蕉好吃");
        ssb.query(qb);
        
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("desc");

        ssb.highlighter(highlightBuilder);

        searchRequest.source(ssb);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String record = hit.getSourceAsString();
            HighlightField highlightField = hit.getHighlightFields().get("desc");

            for (Text fragment : highlightField.getFragments()) {
                System.out.println(fragment.string());
            }
        }
    }

我们重点关注一下HighlightBuilder,我们在发送请求前,创建HighlightBuilder,并指定高亮字段为desc。搜索结束后,我们取结果,从hit当中取出高亮字段desc,然后打印出fragment,运行一下,看看结果吧,

<em>香蕉</em>真<em>好吃</em>
<em>香蕉</em>真<em>好吃</em>
橘子真<em>好吃</em>
桃子真<em>好吃</em>
苹果真<em>好吃</em>

完全符合预期,“香蕉好吃”被分词后,在搜索结果中都增加了<em>标签,我们可不可以自定义高亮标签呢?当然是可以的,我们稍微改一下程序就可以了,

HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("desc");

highlightBuilder.preTags("<b>");
highlightBuilder.postTags("</b>");

ssb.highlighter(highlightBuilder);

HighlightBuilder中,使用preTags添加起始标签,指定为<b>,用postTags添加闭合标签,指定为</b>,再运行一下,看看结果,

<b>香蕉</b>真<b>好吃</b>
<b>香蕉</b>真<b>好吃</b>
橘子真<b>好吃</b>
桃子真<b>好吃</b>
苹果真<b>好吃</b>

结果完全正确,用<b>替换了<em>,是不是很灵活。接下来我们再看看搜索建议。

搜索建议

“搜索建议”这个功能也是相当实用的,当我们在搜索框中输入某个字时,与这个字的相关搜索内容就会罗列在下面,我们选择其中一个搜索就可以了,省去了敲其他字的时间。我们看看ES中是怎么实现“搜索建议”的。

如果要在ES中使用“搜索建议”功能,是需要特殊设置的,要设置一个类型为completion的字段,由于之前的索引中已经有了数据,再添加字段是会报错的,索引我们新建一个索引,

PUT /my_suggester
{
    "settings":{
        "analysis":{
            "analyzer":{
                "default":{
                    "type":"ik_max_word"
                }
            }
        }
    },
    "mappings":{
        "dynamic_date_formats": [
             "MM/dd/yyyy",
             "yyyy/MM/dd HH:mm:ss",
             "yyyy-MM-dd",
             "yyyy-MM-dd HH:mm:ss"
         ],
        "properties":{
            "suggest":{
                "type":"completion"
            }
        }
    }
}

这已经成了我们新建索引的一个标配了,指定分词器为ik中文分词,动态字段的时间映射格式,以及搜索建议字段,注意suggest字段的类型为completion。我们再添加字段的时候,就要为suggest字段添加值了,如下:

POST /my_suggester/_doc
{
    "title":"天气",
    "desc":"今天天气不错",
    "suggest": {
       "input": "天气"
    }
}

POST /my_suggester/_doc
{
    "title":"天空",
    "desc":"蓝蓝的天空,白白的云",
    "suggest": {
       "input": "天空"
    }
}

我们向索引中添加了两条数据,大家需要额外注意的是suggest字段的赋值方法,要使用input,我们看一下数据,

ES[7.6.x]学习笔记(十二)高亮 和 搜索建议

suggest字段并没有像其他字段那样展示出来,说明它和其他字段是不一样的。现在我们如果只输入一个“天”字,看看搜索建议能不能给出提示,如下:

POST /my_suggester/_search
{
  "suggest": {
    "s-test": {
      "prefix": "天",
      "completion": {
        "field": "suggest"
      }
    }
  }
}

在请求体中,suggest就是“搜索建议”的标识,s-test是自定义的一个名称,prefix是前缀,也就是我们输入的“天”字,completion指定搜索建议的字段,我们看看查询的结果,

……
"suggest": {
    "s-test": [
        {
            "text": "天",
            "offset": 0,
            "length": 1,
            "options": [{
                "text": "天气",
                "_index": "my_suggester",
                "_type": "_doc",
                "_id": "QtgAWnIBOZNtuLQtJgpt",
                "_score": 1,
                "_source": { "title": "天气","desc": "今天天气不错","suggest": { "input": "天气"}}
            }
            ,
            {
                "text": "天空",
                "_index": "my_suggester",
                "_type": "_doc",
                "_id": "T9gAWnIBOZNtuLQtWQoX",
                "_score": 1,
                "_source": { "title": "天空","desc": "蓝蓝的天空,白白的云","suggest": { "input": "天空"}}
            }
        ]
        }
    ]
}

s-test.options里,包含了两条记录,text字段就是我们写的建议字段,后面_source里还包含对应的数据,下面我们再看看程序里怎么使用“搜索建议”,

public void searchSuggest(String prefix) throws IOException {
    SearchRequest searchRequest = new SearchRequest("my_suggester");
    SearchSourceBuilder ssb = new SearchSourceBuilder();

    CompletionSuggestionBuilder suggest = SuggestBuilders
        .completionSuggestion("suggest")
        .prefix(prefix);

    SuggestBuilder suggestBuilder = new SuggestBuilder();
    suggestBuilder.addSuggestion("s-test",suggest);

    ssb.suggest(suggestBuilder);

    searchRequest.source(ssb);
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

    CompletionSuggestion suggestion = response.getSuggest().getSuggestion("s-test");
    for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {
        System.out.println(option.getText().string());
    }

}

@Test
public void searchSuggest() throws IOException {
    eService.searchSuggest("天");
}

我们创建了CompletionSuggestionBuilder,通过方法completionSuggestion指定“搜索建议”字段suggest,并且指定前缀为方法传入的prefix,我们在测试的时候传入"天"字。然后,我们自定义“搜索建议”的名字为s-test,传入前面构造好的suggest

发送请求后,在响应中获取前面自定义的s-test,然后循环options,取出text字段,这就是搜索建议的字段,我们运行一下,看看结果,

天气
天空

完全符合预期,这样用户在搜索的时候,就会给出提示信息了。

好了,今天这两个ES的知识点就全部OK了~ 大家有问题在评论区留言。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这