本章内容
文章内容搜索思路
搜索内容分词
搜索查询语句
筛选条件
分页、排序条件
小结

一、文章内容搜索思路
上一篇讲了在怎么在 Spring Boot 2.0 上整合 ES 5 ,这一篇聊聊具体实战。简单讲下如何实现文章、问答这些内容搜索的具体实现。实现思路很简单:

基于「短语匹配」并设置最小匹配权重值
哪来的短语,利用 IK 分词器分词
基于 Fiter 实现筛选
基于 Pageable 实现分页排序
这里直接调用搜索的话,容易搜出不尽人意的东西。因为内容搜索关注内容的连接性。所以这里处理方法比较 low ,希望多交流一起实现更好的搜索方法。就是通过分词得到很多短语,然后利用短语进行短语精准匹配。

ES 安装 IK 分词器插件很简单。第一步,在下载对应版本 https://github.com/medcl/elas...。第二步,在 elasticsearch-5.5.3/plugins 目录下,新建一个文件夹 ik,把 elasticsearch-analysis-ik-5.5.3.zip 解压后的文件拷贝到 elasticsearch-5.1.1/plugins/ik 目录下。最后重启 ES 即可。

二、搜索内容分词

安装好 IK ,如何调用呢?

第一步,我这边搜搜内容会以 逗号 拼接传入。所以会先将逗号分割

第二步,在搜索词中加入自己本身,因为有些词经过 ik 分词后就没了... 这是个 bug

第三步,利用 AnalyzeRequestBuilder 对象获取 IK 分词后的返回值对象列表

第四步,优化分词结果,比如都为词,则保留全部;有词有字,则保留词;只有字,则保留字

核心实现代码如下:

   /*** 搜索内容分词*/protected List<String>      handlingSearchContent(String searchContent) {List<String> searchTermResultList = new ArrayList<>();// 按逗号分割,获取搜索词列表List<String> searchTermList = Arrays.asList(searchContent.split(SearchConstant.STRING_TOKEN_SPLIT));// 如果搜索词大于 1 个字,则经过 IK 分词器获取分词结果列表searchTermList.forEach(searchTerm -> {// 搜索词 TAG 本身加入搜索词列表,并解决 will 这种问题searchTermResultList.add(searchTerm);// 获取搜索词 IK 分词列表searchTermResultList.addAll(getIkAnalyzeSearchTerms(searchTerm));});return searchTermResultList;}/*** 调用 ES 获取 IK 分词后结果*/protected List<String>      getIkAnalyzeSearchTerms(String searchContent) {AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(),AnalyzeAction.INSTANCE, SearchConstant.INDEX_NAME,      searchContent);ikRequest.setTokenizer(SearchConstant.TOKENIZER_IK_MAX);List<AnalyzeResponse.AnalyzeToken> ikTokenList =      ikRequest.execute().actionGet().getTokens();// 循环赋值List<String> searchTermList = new ArrayList<>();ikTokenList.forEach(ikToken -> {searchTermList.add(ikToken.getTerm());});return handlingIkResultTerms(searchTermList);}/*** 如果分词结果:洗发水(洗发、发水、洗、发、水)* - 均为词,保留* - 词 + 字,只保留词* - 均为字,保留字*/private List<String>      handlingIkResultTerms(List<String> searchTermList) {Boolean isPhrase = false;Boolean isWord = false;for (String term : searchTermList) {if (term.length() > SearchConstant.SEARCH_TERM_LENGTH)      {isPhrase = true;} else {isWord = true;}}if (isWord & isPhrase) {List<String> phraseList = new ArrayList<>();searchTermList.forEach(term -> {if (term.length() > SearchConstant.SEARCH_TERM_LENGTH)      {phraseList.add(term);}});return phraseList;}return searchTermList;}

三、搜索查询语句

构造内容枚举对象,罗列需要搜索的字段,ContentSearchTermEnum 代码如下:

import lombok.AllArgsConstructor;@AllArgsConstructor
public enum ContentSearchTermEnum {// 标题TITLE("title"),// 内容CONTENT("content");/*** 搜索字段*/private String      name;public String      getName() {return name;}public void      setName(String name) {this.name = name;}}

循环进行「短语搜索匹配」搜索字段,然后并设置最低权重值为 1。核心代码如下:

   /*** 构造查询条件*/private void      buildMatchQuery(BoolQueryBuilder queryBuilder, List<String>      searchTermList) {for (String searchTerm : searchTermList) {for (ContentSearchTermEnum searchTermEnum : ContentSearchTermEnum.values())      {queryBuilder.should(QueryBuilders.matchPhraseQuery(searchTermEnum.getName(),      searchTerm));}}queryBuilder.minimumShouldMatch(SearchConstant.MINIMUM_SHOULD_MATCH);}

四、筛选条件
搜到东西不止,有时候需求是这样的。需要在某个品类下搜索,比如电商需要在某个 品牌 下搜索商品。那么需要构造一些 fitler 进行筛选。对应 SQL 语句的 Where 下的 OR 和 AND 两种语句。在 ES 中使用 filter 方法添加过滤。代码如下:

   /*** 构建筛选条件*/private void      buildFilterQuery(BoolQueryBuilder boolQueryBuilder, Integer type, String      category) {// 内容类型筛选if (type != null) {BoolQueryBuilder typeFilterBuilder = QueryBuilders.boolQuery();typeFilterBuilder.should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME,      type).lenient(true));boolQueryBuilder.filter(typeFilterBuilder);}// 内容类别筛选if (!StringUtils.isEmpty(category)) {BoolQueryBuilder categoryFilterBuilder = QueryBuilders.boolQuery();categoryFilterBuilder.should(QueryBuilders.matchQuery(SearchConstant.CATEGORY_NAME,      category).lenient(true));boolQueryBuilder.filter(categoryFilterBuilder);}}

type 是大类,category 是小类,这样就可以支持 大小类 筛选。但是如果需要在 type = 1 或者 type = 2 中搜索呢?具体实现代码很简单:

typeFilterBuilder.should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME,      1).should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME,      2).lenient(true));

通过链式表达式,两个 should 实现或,即 SQL 对应的 OR 语句。通过两个 BoolQueryBuilder 实现与,即 SQL 对应的 AND 语句。

五、分页、排序条件

分页排序代码就很简单了:

  @Overridepublic PageBean      searchContent(ContentSearchBean contentSearchBean) {Integer pageNumber = contentSearchBean.getPageNumber();Integer pageSize = contentSearchBean.getPageSize();PageBean<ContentEntity> resultPageBean = new PageBean<>();resultPageBean.setPageNumber(pageNumber);resultPageBean.setPageSize(pageSize);// 构建搜索短语String searchContent = contentSearchBean.getSearchContent();List<String> searchTermList =      handlingSearchContent(searchContent);// 构建查询条件BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();buildMatchQuery(boolQueryBuilder, searchTermList);// 构建筛选条件buildFilterQuery(boolQueryBuilder, contentSearchBean.getType(),      contentSearchBean.getCategory());// 构建分页、排序条件Pageable pageable = PageRequest.of(pageNumber, pageSize);if (!StringUtils.isEmpty(contentSearchBean.getOrderName())) {pageable = PageRequest.of(pageNumber, pageSize, Sort.Direction.DESC,      contentSearchBean.getOrderName());}SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(boolQueryBuilder).build();// 搜索LOGGER.info("\n ContentServiceImpl.searchContent() [" +      searchContent+ "] \n DSL  = \n " +      searchQuery.getQuery().toString());Page<ContentEntity> contentPage =      contentRepository.search(searchQuery);resultPageBean.setResult(contentPage.getContent());resultPageBean.setTotalCount((int) contentPage.getTotalElements());resultPageBean.setTotalPage((int) contentPage.getTotalElements() /      resultPageBean.getPageSize() + 1);return resultPageBean;}

利用 Pageable 对象,构造分页参数以及指定对应的 排序字段、排序顺序(DESC ASC)即可。

文章来源:http://mp.weixin.qq.com/s/ZoJ...
更多springboot参考内容:http://www.roncoo.com/article...

Spring Boot 2.0 整合 ES 5 文章内容搜索实战相关推荐

  1. html页面授权码,spring boot 2.0 整合 oauth2 authorization code授权码模式

    oauth2 authorization code 大致流程 用户打开客户端后,客户端要求用户给予授权. 用户同意给予客户端授权. 客户端使用授权得到的code,向认证服务器申请token令牌. 认证 ...

  2. 实战Spring Boot 2.0系列(一) - 使用Gradle构建Docker镜像

    前言 通常我们使用 Dockerfile 来构建项目的 Docker 镜像.但是也有使用 gradle 在编译项目的时候一起把镜像给 构建 并 上传 的需求.本文将会讲解如何使用 gradle 编写并 ...

  3. Spring Boot 3.0 新书终于出炉,荣获京东计算机图书排行榜 TOP 1!

    大家好,我是R哥. 我的新书<Spring Boot 3 核心技术与最佳实践>折腾一年多,终于在昨天上市了,太不容易了... 有需要的可以购买学习: 本书定价 158 元,刚上市搞 5 折 ...

  4. Elasticsearch-06 Spring Boot 2.0.9整合ElasticSearch5.6.16

    文章目录 概述 官方JAVA API文档 工程 pom.xml es配置文件 Es配置类 控制层 简单查询 新增数据 删除数据 更新数据 复合查询 其他 新建索引 删除索引 判断index中某个typ ...

  5. Spring Boot 综合示例-整合thymeleaf、mybatis、shiro、logging、cache开发一个文章发布管理系统...

    一.概述 经过HelloWorld示例(Spring Boot 快速入门(上)HelloWorld示例)( Spring Boot  快速入门 详解 HelloWorld示例详解)两篇的学习和练习,相 ...

  6. Spring Boot 2.0系列文章(四):Spring Boot 2.0 源码阅读环境搭建

    前提 前几天面试的时候,被问过 Spring Boot 的自动配置源码怎么实现的,没看过源码的我只能投降��了. 这不,赶紧来补补了,所以才有了这篇文章的出现,Spring Boot 2. 0 源码阅 ...

  7. spring boot 2.0.3.RELEASE 整合 shiro bug 记录

    spring boot 2.0.3.RELEASE 和 shiro 结合的 bug 纪要: 1.shiro 的过滤器 会出现在所有的过滤链中,尽管该请求不包含在shiro过滤规则中,尽管不会进入shi ...

  8. 【译】Spring Boot 2.0 官方迁移指南

    前提 希望本文档将帮助您把应用程序迁移到 Spring Boot 2.0. 在你开始之前 首先,Spring Boot 2.0 需要 Java 8 或更高版本.不再支持 Java 6 和 7 了. 在 ...

  9. SpringBoot2.0(一):【重磅】Spring Boot 2.0权威发布

    就在昨天Spring Boot2.0.0.RELEASE正式发布,今天早上在发布Spring Boot2.0的时候还出现一个小插曲,将Spring Boot2.0同步到Maven仓库的时候出现了错误, ...

  10. Spring Boot 2.0 迁移指南

    点击上方"朱小厮的博客",选择"设为星标" 回复"666"获取新整理的1000+GB资料 前提 本文档将帮助您把应用程序迁移到 Spring ...

最新文章

  1. HDU2988(Kruskal算法模版)
  2. Java字节流文件流的练习
  3. mysql5.7编译安装路径_MySQL_MySQL 5.5/5.6/5.7及以上版本安装包安装时如何选择安装路径,安装环境需求: 自从昨天安 - phpStudy...
  4. Sitemesh 3 的使用及配置
  5. 【python+selenium自动化】使用pytest+allure2完成自动化测试报告的输出
  6. 数据库 查询XML XQuery
  7. 【BZOJ3998】弦论(后缀自动机)
  8. layui里面layer弹窗渲染layerdate,时间控件不出现,闪现问题,F12才出来
  9. EXP6 信息搜集与漏洞扫描 20154328 常城
  10. 批量取消关注和删除微博
  11. 云智慧透视宝Java代码性能监控实现原理
  12. Unity笔记-29-ARPG游戏项目-12-完善弓箭
  13. python 一元二次方程计算器
  14. 固定资产拆分比例怎么计算_固定资产折旧的计算方法
  15. 通过电话拨号上网的家用计算机,拨号上网需计算机、电话线、帐号和()
  16. 航顺HK32F030MF4P6开发脱坑小记
  17. vue导出excel加一个进度条_Vue实现在前端导出Excel
  18. sklearn专题六:聚类算法K-Means
  19. Spring官网阅读(四)BeanDefinition(上)
  20. 餐饮门店每日业务情况数据分析仪表盘(外卖平台)

热门文章

  1. js时间戳转化成日期格式
  2. Hadoop 服务器配置的副本数量 管不了客户端
  3. zoj 3747 dp递推
  4. linux下PHP后台配置极光推送问题
  5. IT部门域事件与业务分析
  6. CheckBox的触发
  7. HDOJ-2095 Find your present (2) / NYOJ-528 找球号(三)
  8. 使用@Aspect切面进行让JDBC自动关闭(Spring AOP)
  9. 商城管理系统(前台+后台+管理员+用户+html+jsp)
  10. 从客户端中检测到有潜在危险的 request.form值