一、开门见山

首先es全称 Elasticsearch 目的是为了快速查找出我们想要的数据
在我们的软件中,搜索栏是用到最多的,找出对应的关联词
image.png image.png

认识es

那es的基本结构是什么?
Elasticsearch 是一种NoSQL数据库(非关系型数据库),和常规的关系型数据库(比如:MySQL,Oralce等)的基本概念,对应关系如下:

  • Elasticsearch:index —> type —> doc —> field
  • MySQL: 数据库 —> 数据表 —> 行 —> 列

ES特点和优势
1)分布式实时文件存储,可将每一个字段存入索引,使其可以被检索到。
2)实时分析的分布式搜索引擎。
分布式:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作;
负载再平衡和路由在大多数情况下自动完成。
3)可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。也可以运行在单台PC上(已测试)
4)支持插件机制,分词插件、同步插件、Hadoop插件、可视化插件等。

二、进入实战

1、初步认识

先从一个之前的需求进行介绍:
image.png

组装搜索参数对象

  1. // 组装搜索参数对象
  2. ServicePackDetailParam servicePackDetailParam = new ServicePackDetailParam(condition.getSearch(), condition.getAddrArea(), sort, condition.getStart(), condition.getLimit());

之后添加过滤条件

  1. fullServicePackFilter(condition, servicePackDetailParam);

image.png

排除指定的对象后,进入es模块查询

  1. List<ServicePackDetailVO> servicePackDetailVOS = organDetailService.searchServicePackDetails(servicePackDetailParam);

image.png
image.png

前面会进行条件的匹配,创建搜索生成器

  1. NativeSearchQueryBuilder builder = createSearchBuilder(param);

在其中会进行,查询条件的进一步细化,如
matchPhraseQuery相当于like的模糊匹配. minimumShouldMatch表示最小需要匹配到的should数,并向下取整
image.png

以下是真正的查询语句

  1. SearchHits<ServicePackDetail> results = queryService.getElasticsearchRestTemplate().search(query, ServicePackDetail.class, ElasticUtil.getIndex(ServicePackDetail.class));

之后设置高亮显示
image.png
完成需求!如需要更详细es操作见 —-> click

2、快速入手

我们简单写一个程序,定时查询含关键字的医生联想词

  • 接口

配置接口,具体的业务处理在对应的类中
image.png

  • 业务

image.png
跳转过来后,查看:
创建搜索条件的对象DoctorDetailParam 用来组装搜索参数,之后的过滤或者排除都通过对设置这个对象实现

  1. DoctorDetailParam param = new DoctorDetailParam();

如之后过滤当前用户所在的机构,排除其他无关机构

  1. for(Integer oid : organIdList) {
  2. param.filter(DoctorDetailVO.ORGAN_ID, oid);
  3. }

调用es.doctorDetailService接口,交给es查询

  1. List<DoctorDetailVO> doctorDetailVOS = doctorDetailService.searchDoctorDetails(param);
  • es查询

image.png
其中出现了一个重要的对象BoolQueryBuilder,这个对象就是用来 关联存放所有查询条件,我理解成索引

  1. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

之后就是条件的添加了,往boolQueryBuilder里,涉及到一些规范:

  • minimumShouldMatch表示最小需要匹配到的should数
  • must完全匹配
  • mustNot完全不匹配

  • matchPhraseQuery相当于like的模糊匹配

  • prefixQuery前缀查询
  • termQuery词条查询,相当于完全匹配

最后就是封装成NativeSearchQueryBuilder对象了

  1. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
  2. .withQuery(boolQueryBuilder)
  3. .withSearchType(SearchType.QUERY_THEN_FETCH)
  4. .withPageable(PageRequest.of(param.getStart()/param.getLimit(), param.getLimit()));
  5. configSortsByParam(nativeSearchQueryBuilder,param);

然后构建成查询条件NativeSearchQuery query

  1. NativeSearchQuery query = nativeSearchQueryBuilder
  2. .withHighlightFields(new HighlightBuilder.Field(DoctorDetailVO.DOCTOR_NAME),
  3. new HighlightBuilder.Field(DoctorDetailVO.DOMAIN),
  4. new HighlightBuilder.Field(DoctorDetailVO.ORGAN_NAME),
  5. new HighlightBuilder.Field(DoctorDetailVO.PROFESSION_NAME),
  6. new HighlightBuilder.Field(DoctorDetailVO.NURSE_WORK_PROJECT_ID))
  7. .build();

调用QueryService queryService;对象去查询了,获取一个获取SearchHits集合

  1. SearchHits<DoctorDetail> result = queryService.getElasticsearchRestTemplate().search(query, DoctorDetail.class, ElasticUtil.getIndex(DoctorDetail.class));

最后完成数据的转换
将 SearchHits 转换成 List,并且将高亮部分前后加上‘,举例:

  1. List<DoctorDetail> doctorDetails = result.get().map(searchHit -> {
  2. DoctorDetail content = searchHit.getContent();
  3. DoctorDetail doctorDetail = BeanUtil.copyProperties(content, DoctorDetail.class);
  4. List<String> valuesDoc = searchHit.getHighlightField(DoctorDetailVO.DOCTOR_NAME);
  5. String joinDoctorName = checkListHasValue(valuesDoc) ? doctorDetail.getDoctorName() : valuesDoc.get(0);
  6. doctorDetail.setHighlightDoctorName(joinDoctorName);
  7. return doctorDetail;
  8. }).collect(Collectors.toList());
  • 结果查询

image.png

3、扩展部分流程

可能在一个完整的流程中,会存在busType业务类型去规定排序规则,
以下为 保存为历史搜索记录
image.png
当然还有排序规则
image.png
列举两种服务,图文咨询、电话咨询,调整根据不同的serviceType选取DoctorSort配置
image.png
image.png
DoctorSort枚举类的相关配置
image.png
在下面添加真正的排序规则,排序权重越前面越大
image.png
配置好根据业务类型 排序好之后,那我们会在哪用到这个排序呢?
image.png
就是在es模块的createSearchBuilder()配置中
image.png
进行排序规则的填充
image.png

  1. // withSort 配置排序规则值构造器
  2. builder.withSort(SortBuilders.fieldSort(sortEntry.getKey()).order(sortEntry.getValue()));

通过busType查询结果
image.png

  • Tips

Hibernate中数据库表与类绑定,通过this. 就可以调用到该DAO下的方法。
image.png

三、梳理总结

无论是这里用到的es工具,还是以后学习的其他工具,要深入可以访问文档下的es基础。

还有es-head的说明书也在分布式的知识库下。

es交互的场景

为了方便今后代码的编写,以下为总结梳理纳里健康业务上与es交互的场景
医生列表
image.png
机构列表、
image.png
健康管理列表、

image.png
医生联想、**

  1. public List<String> searchDoctorTermES(String term,int start,int limit) {

image.png
机构联想

image.png