一、开门见山
首先es全称 Elasticsearch 目的是为了快速查找出我们想要的数据
在我们的软件中,搜索栏是用到最多的,找出对应的关联词
认识es
那es的基本结构是什么?
Elasticsearch 是一种NoSQL数据库(非关系型数据库),和常规的关系型数据库(比如:MySQL,Oralce等)的基本概念,对应关系如下:
- Elasticsearch:index —> type —> doc —> field
- MySQL: 数据库 —> 数据表 —> 行 —> 列
ES特点和优势
1)分布式实时文件存储,可将每一个字段存入索引,使其可以被检索到。
2)实时分析的分布式搜索引擎。
分布式:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作;
负载再平衡和路由在大多数情况下自动完成。
3)可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。也可以运行在单台PC上(已测试)
4)支持插件机制,分词插件、同步插件、Hadoop插件、可视化插件等。
二、进入实战
1、初步认识
先从一个之前的需求进行介绍:
组装搜索参数对象
// 组装搜索参数对象
ServicePackDetailParam servicePackDetailParam = new ServicePackDetailParam(condition.getSearch(), condition.getAddrArea(), sort, condition.getStart(), condition.getLimit());
之后添加过滤条件
fullServicePackFilter(condition, servicePackDetailParam);
排除指定的对象后,进入es模块查询
List<ServicePackDetailVO> servicePackDetailVOS = organDetailService.searchServicePackDetails(servicePackDetailParam);
前面会进行条件的匹配,创建搜索生成器
NativeSearchQueryBuilder builder = createSearchBuilder(param);
在其中会进行,查询条件的进一步细化,如
matchPhraseQuery相当于like的模糊匹配. minimumShouldMatch表示最小需要匹配到的should数,并向下取整
以下是真正的查询语句
SearchHits<ServicePackDetail> results = queryService.getElasticsearchRestTemplate().search(query, ServicePackDetail.class, ElasticUtil.getIndex(ServicePackDetail.class));
之后设置高亮显示
完成需求!如需要更详细es操作见 —-> click
2、快速入手
我们简单写一个程序,定时查询含关键字的医生联想词
- 接口
配置接口,具体的业务处理在对应的类中
- 业务
跳转过来后,查看:
创建搜索条件的对象DoctorDetailParam 用来组装搜索参数,之后的过滤或者排除都通过对设置这个对象实现
DoctorDetailParam param = new DoctorDetailParam();
如之后过滤当前用户所在的机构,排除其他无关机构
for(Integer oid : organIdList) {
param.filter(DoctorDetailVO.ORGAN_ID, oid);
}
调用es.doctorDetailService接口,交给es查询
List<DoctorDetailVO> doctorDetailVOS = doctorDetailService.searchDoctorDetails(param);
- es查询
其中出现了一个重要的对象BoolQueryBuilder,这个对象就是用来 关联存放所有查询条件,我理解成索引
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
之后就是条件的添加了,往boolQueryBuilder里,涉及到一些规范:
- minimumShouldMatch表示最小需要匹配到的should数
- must完全匹配
mustNot完全不匹配
matchPhraseQuery相当于like的模糊匹配
- prefixQuery前缀查询
- termQuery词条查询,相当于完全匹配
最后就是封装成NativeSearchQueryBuilder对象了
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withSearchType(SearchType.QUERY_THEN_FETCH)
.withPageable(PageRequest.of(param.getStart()/param.getLimit(), param.getLimit()));
configSortsByParam(nativeSearchQueryBuilder,param);
然后构建成查询条件NativeSearchQuery query
NativeSearchQuery query = nativeSearchQueryBuilder
.withHighlightFields(new HighlightBuilder.Field(DoctorDetailVO.DOCTOR_NAME),
new HighlightBuilder.Field(DoctorDetailVO.DOMAIN),
new HighlightBuilder.Field(DoctorDetailVO.ORGAN_NAME),
new HighlightBuilder.Field(DoctorDetailVO.PROFESSION_NAME),
new HighlightBuilder.Field(DoctorDetailVO.NURSE_WORK_PROJECT_ID))
.build();
调用QueryService queryService;对象去查询了,获取一个获取SearchHits
SearchHits<DoctorDetail> result = queryService.getElasticsearchRestTemplate().search(query, DoctorDetail.class, ElasticUtil.getIndex(DoctorDetail.class));
最后完成数据的转换
将 SearchHits 转换成 List
List<DoctorDetail> doctorDetails = result.get().map(searchHit -> {
DoctorDetail content = searchHit.getContent();
DoctorDetail doctorDetail = BeanUtil.copyProperties(content, DoctorDetail.class);
List<String> valuesDoc = searchHit.getHighlightField(DoctorDetailVO.DOCTOR_NAME);
String joinDoctorName = checkListHasValue(valuesDoc) ? doctorDetail.getDoctorName() : valuesDoc.get(0);
doctorDetail.setHighlightDoctorName(joinDoctorName);
return doctorDetail;
}).collect(Collectors.toList());
- 结果查询
3、扩展部分流程
可能在一个完整的流程中,会存在busType业务类型去规定排序规则,
以下为 保存为历史搜索记录
当然还有排序规则
列举两种服务,图文咨询、电话咨询,调整根据不同的serviceType选取DoctorSort配置
DoctorSort枚举类的相关配置
在下面添加真正的排序规则,排序权重越前面越大
配置好根据业务类型 排序好之后,那我们会在哪用到这个排序呢?
就是在es模块的createSearchBuilder()配置中
进行排序规则的填充
// withSort 配置排序规则值构造器
builder.withSort(SortBuilders.fieldSort(sortEntry.getKey()).order(sortEntry.getValue()));
通过busType查询结果
- Tips
Hibernate中数据库表与类绑定,通过this. 就可以调用到该DAO下的方法。
三、梳理总结
无论是这里用到的es工具,还是以后学习的其他工具,要深入可以访问文档下的es基础。
- 点击——>es-基础
还有es-head的说明书也在分布式的知识库下。
- 点击——>es-head
es交互的场景
为了方便今后代码的编写,以下为总结梳理纳里健康业务上与es交互的场景
医生列表
机构列表、
健康管理列表、
医生联想、**
public List<String> searchDoctorTermES(String term,int start,int limit) {
机构联想