文章目录

  • 前言
  • 一、如何使用ES做类似百度的检索?
  • 二、全文检索自动补齐
    • 1.创建索引
    • 2.添加数据
    • 3.高级检索
  • 三 热搜词
    • 1.思路
    • 2.DSL语句
    • 3.java代码实现
    • 四 拼音补全
    • 1.DSL语法
    • 2.java代码实现
  • 总结

前言

前面讲了springboot集成ES的两种方法和es简单的增删改查,那么针对高级检索,es在7.x推荐的restclinet采用的查询方式需要了解del语言格式,那么今天来简单对dsl语言转化成java代码进行一个学习


一、如何使用ES做类似百度的检索?

1.先来回想一下,百度搜索的风格,在进行百度搜索时,百度首页会出现一个热搜词

2.在使用搜索框搜索时,会进行搜索补全


3.使用拼音可以进行检索

二、全文检索自动补齐

1.创建索引

一般来说,输入框提示出来的词都是经常被搜索的词,所以全文检索检索的是对应的热搜词的索引。

1.创建索引,并且为了后续做拼音检索,应该对检索的fileName字段采用拼音分词器分词和ik分词器两种分词方式。但是这儿的hot词使用的是keyword,不能进行拼音分词。

猜想:fileds可以设置多个字段,这个后面找时间来验证

{"properties": {"createTime": {"type": "date","format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis"},"searchInput": {"type": "completion","analyzer": "ik_max_word","fields": {"hot": {"type": "keyword"  //用于热搜词}}}}
}

猜想结构:

{"properties": {"createTime": {"type": "date","format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis"},"searchInput": {"type": "completion","analyzer": "ik_max_word","fields": {"hot": {"type": "keyword"  //用于热搜词},"hot-py":{"type": "text","term_vector": "with_positions_offsets","analyzer": "pinyin_analyzer", //用于热搜拼音"boost": 10.0}}}}
}

2.添加数据

我是使用封装的工具类进行的添加数据,当然可以使用repository使用

    /*** 新增数据,自定义id** @param object 要增加的数据* @param index  索引,类似数据库* @param id     数据ID,为null时es随机生成* @return*/public String addData(Object object, String index, String id) throws IOException {if (null == id) {return addData(object, index);}if (this.existsById(index, id)) {return this.updateDataByIdNoRealTime(object, index, id);}//创建请求IndexRequest request = new IndexRequest(index);request.id(id);request.timeout(TimeValue.timeValueSeconds(1));//将数据放入请求 jsonrequest.source(JSON.toJSONString(object), XContentType.JSON);//客户端发送请求IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);log.info("添加数据成功 索引为: {}, response 状态: {}, id为: {}", index, response.status().getStatus(), response.getId());return response.getId();}

3.高级检索

1.自动补全功能在es中是提供了这个功能的,需要定义查询对象 SuggestBuilder ,suggest类型下有几种类型:

suggest term: 根据 编辑距离(edit distance) 给出提示、建议,给出的结果是单个词
suggest phrase: 在Term suggester的基础上,会考量多个term之间的关系,比如是否同时出现在索引的原文里,相邻程度,以及词频等等。给出的结果是一个句子
suggest completion: 定义特殊字段,用于提示不全。字段type需要定义为:completion, 数据会编码成FST,索引一起存放,FST都会加载到内存中。只能用于前缀补全。

DSL查询语句demo

{"suggest": {"suggest": {"prefix": "猫","completion": {"field": "search_input.hot","size": 10}}}
}

suggest:代表接下来的查询是一个suggest类型的查询
suggest:这次查询的名称,自定义
prefix:用来补全的词语前缀,本例中搜索以 猫开头的内容
completion:代表是completion类型的suggest,其它类型还有:Term、Phrase
field:要查询的字段

2.java代码实现

    @Overridepublic Set getSearchSuggest(Integer pageSize,String key){//定义suggest对象SuggestBuilder suggestBuilder = new SuggestBuilder();//定义本次查询名字SEARCH_INPUT = suggest,设置prefix 补齐前缀,查询个数pagesize个,skipDuplicates去除重复数据CompletionSuggestionBuilder suggestion = SuggestBuilders.completionSuggestion(SEARCH_INPUT).prefix(key).size(pageSize).skipDuplicates(true);suggestBuilder.addSuggestion(SEARCH_SUGGEST,suggestion);SearchRequest request = new SearchRequest().indices(ESConst.HOT_KEY_INDEX).source(new SearchSourceBuilder().suggest(suggestBuilder));//可以通过设置searchsourcebuilder来设置_source过滤字段SearchResponse searchResponse = null;try {searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);System.out.println(searchResponse);} catch (IOException e) {e.printStackTrace();}Suggest suggest = searchResponse.getSuggest();Set<String> keywords = null;if (suggest != null) {keywords = new HashSet<>();List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries = suggest.getSuggestion(SEARCH_SUGGEST).getEntries();for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry: entries) {for (Suggest.Suggestion.Entry.Option option: entry.getOptions()) {/** 最多返回9个推荐,每个长度最大为20 */String keyword = option.getText().string();if (!StringUtils.isEmpty(keyword) && keyword.length() <= 20) {/** 去除输入字段 */if (keyword.equals(key)) continue;keywords.add(keyword);if (keywords.size() >= pageSize) {break;}}}}}return keywords;}

自此,可以简单的得到检索时的补全词汇集合;当然也可以设置纠错词汇,只需要修改suggest对象类型。


三 热搜词

1.思路

热搜词的关键在于,需要查询什么。一般来说热搜词为数量最多的词。所以,我在全文检索时对流媒体进行查询时,会写一个切面类,在查询之前,将输入框中的词保存到es的热搜词索引中。那么就简单,我们只需要对hot-key的索引进行分组查询,算出个数最多的词进行排序。

2.DSL语句

es中的aggregations聚合,相当于SQL中的group by
es聚合分为四种方式:指标聚合,桶聚合,矩阵聚合,管道聚合。

单个分组用指标聚合,terms相当于分组后统计各组的count结果

 "aggs": {"hot_count" : {"terms" : {"field" : "search_input.hot"}}}

3.java代码实现

    @Overridepublic List<Map<String, Object>> getHotKey(Integer pageSize,String type) {SearchRequest searchRequest = new SearchRequest(ESConst.HOT_KEY_INDEX);//构建搜索条件SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//select keyword, count(*) as hot_count from hot-key group by keyword;  -- > 分组TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms(HOT_COUNT).field(SEARCH_INPUT+".hot");//不需要解释sourceBuilder.explain(false);//不需要原始数据sourceBuilder.fetchSource(false);//不需要版本号sourceBuilder.version(false);sourceBuilder.aggregation(aggregationBuilder);RangeQueryBuilder rangeQueryBuilder = null;switch (type){case ESConst.MONTH: rangeQueryBuilder = QueryBuilders.rangeQuery("createTime").gte(LocalDateTime.now().minusMonths(1).format(formatter)).lte(LocalDateTime.now().format(formatter));break;case ESConst.WEEK: rangeQueryBuilder = QueryBuilders.rangeQuery("createTime").gte(LocalDateTime.now().minusWeeks(1).format(formatter)).lte(LocalDateTime.now().format(formatter));break;case ESConst.DAY: rangeQueryBuilder = QueryBuilders.rangeQuery("createTime").gte(LocalDateTime.now().minusDays(1).format(formatter)).lte(LocalDateTime.now().format(formatter));break;default: rangeQueryBuilder = QueryBuilders.rangeQuery("createTime").gte(LocalDateTime.now().minusDays(1).format(formatter)).lte(LocalDateTime.now().format(formatter));break;}//时间范围sourceBuilder.query(rangeQueryBuilder);searchRequest.source(sourceBuilder);try {SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println(searchResponse);Terms terms = searchResponse.getAggregations().get(HOT_COUNT);List<Map<String,Object>> result = new ArrayList<>();for (Terms.Bucket bucket : terms.getBuckets()) {Map<String, Object> map = new HashMap<>();map.put("hotKey", bucket.getKeyAsString());map.put("hotValue",bucket.getDocCount());result.add(map);}return result;} catch (IOException e) {e.printStackTrace();}return null;}

四 拼音补全

下面的代码还未经过测试,只是我想象的使用方法,后面我会进行尝试

1.DSL语法

{"suggest": {"suggest": {"prefix": "猫","completion": {"field": "suggestion","size": 10}},"py_suggest":{"prefix": "maohe","completion": {"field": "search_input.py-hot","size": 10}}}
}

因为searchinput字段在创建时mapping映射了两种分词,所以我想,在后面加一个查询条件应该没有问题

2.java代码实现

在原有的java代码基础上,在其中添加对应的py_suggest自定义字段的查询

     /*尝试拼音补全*/CompletionSuggestionBuilder pysuggestion = SuggestBuilders.completionSuggestion(SEARCH_INPUT+".hot-py").prefix(key).size(pageSize).skipDuplicates(true);suggestBuilder.addSuggestion("py_suggest",pysuggestion);/*------------------*/

总结

dsl语言不用记住,当需要使用的时候进行百度,只需要知道es中对象创建和处理遵循的dsl语言的结构便可以写出java代码

ES 7.X 做类百度搜索,进行搜索自动补全和热搜词及拼音功能实现相关推荐

  1. Qt安装后要做的第一件事------Qt自动补全代码快捷键和输入法切换快捷键 的冲突解决 (附:fedora下查询 删除软件命令)...

    遥想当年初接触qt,只要能要就心满意足了.随着不断学习,发现了越来越多的问题.在linux环境下,qt自动补全代码的快捷键是ctrl+space,而输入法的切换启动快捷键也是如此,这就冲突了!导致qt ...

  2. 基于java的微信小程序的实现(十)用户搜索及热搜词相关功能后端实现

    文章目录 1.添加热搜词功能 1.数据库表结构分析 2.需求分析 3.代码实现 2.查询热搜词功能 1.需求分析 2.代码实现 3.搜索功能的实现 1.需求分析 2.自定义模糊查询 1.添加热搜词功能 ...

  3. Ajax实现搜索联想 自动补全

    什么是搜索联想?自动补全? .百度是一个很典型的代表.在百度的搜索框中输入相关信息的时候,会有搜索联想以及自动补全. .搜索联想和自动补全:实际上是为了方便用户的使用.让用户的体验更好. .搜索联想: ...

  4. 搜索框自动补全(模糊匹配)功能实现

    本地实现了一个搜索框自动补全的小功能,在JQuery UI的autocomplete插件的基础上,加入了自己的业务代码,贴出来回顾一下,同时可以给大家一个参考 首先贴出的是JQuery Ui 的自动补 ...

  5. elasticsearch模仿淘宝、京东、百度、谷歌搜索,自动补全、自动完成

    Elasticsearch(简称es)是一款功能强大的开源分布式实时搜索引擎,在日志分析.企业级搜索.时序分析等领域有广泛应用,几乎是各大公司搜索分析引擎的开源首选方案.本文不讲废话,不谈理论,目的在 ...

  6. php redis 搜索,php使用redis做热搜词排行榜

    最近,b2c商城项目中,要做热搜词排行榜,用sql数据库做:建立一张表,保存用户的搜索记录,然后count每一个搜索词,并按照count的次数降序排列.这样的话,对数据库的I/O太频繁了,而且在cou ...

  7. 百度搜索自动补全(百度搜索常见api)

    一.百度搜索常用api 百度搜索常用api 一.搜索关键字自动补全 (一)数据源 https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=关键词 ...

  8. ES系列、Elasticsearch Suggester API(自动补全)

    1.概念 1.1 补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comp ...

  9. Elasticsearch 分布式搜索引擎 -- 自动补全(拼音分词器、自定义分词器、自动补全查询、实现搜索框自动补全)

    文章目录 1. 自动补全 1.1 拼音分词器 1.2.1 自定义分词器 1.2.2 小结 1.2 自动补全 1.3 实现酒店搜索框自动补全 1.3.1 修改酒店映射结构 1.3.2 修改HotelDo ...

最新文章

  1. HTML的checkbox和radio的美化
  2. Object类中的两个方法——wait和notify使用总结
  3. java synchronized 对指定代码添加锁-简单样例
  4. java里shake是什么意思_shake是什么意思_shake在线翻译_英语_读音_用法_例句_海词词典...
  5. Linux中Tomcat 服务的搭建
  6. pillow是python的图像处理标准库_详解Python图像处理库Pillow常用使用方法
  7. 5.1 损坏联机日志的恢复方法
  8. 当红“元宇宙”需要冷思考,听听科幻作家、清华教授和阿里专家怎么说
  9. 通达信的指标公式改为条件选股公式,进行预警
  10. 计算方法(三)分段线性插值和Hermite插值
  11. PCB封装-正片与负片
  12. nginx禁止某些指定的浏览器标识来爬我们网站
  13. poiExcel格式设置,很好用,感谢大佬
  14. 普通人最缺乏的深度思考能力,该如何培养?
  15. win10默认浏览器里多余了一个无效选项
  16. 可以免费发布本地生活分类信息的网站大全
  17. 2D高德Android地图SDK 新手入门的com.amap.api.maps.MapView的坑
  18. SATA硬盘与ATA硬盘区别
  19. 《终结拖延症》重新拥有计划每天的自信和控制力
  20. 总结提高关键词排名最全的41个技巧

热门文章

  1. matlab矩阵错位相加,矩阵的旋转和相加——数组实现
  2. JavaWeb入门(四) I-O
  3. 恰到好处的挫折:在最深的绝望,遇见最美的意外 ~ 【美】 格雷格 · S · 里德...
  4. 潘爱民:Windows系统程序员的“内功”修炼
  5. org.hibernate.AssertionFailure:collection[......] was not processed by flush()
  6. 中国传感器制造运行形势分析及前景趋势预测报告2022-2028年
  7. Arduino 制作PPT红外控制器
  8. 基于springboot+vue的智慧幼儿园管理系统
  9. Vulnhub靶机:VEGETA_ 1
  10. 内生性!内生性!解决方法大集合