Elasticsearch 父子关系维护和检索案例分享,展示has_child和has_parent的基本用法。
本文涉及技术点:
- 1.删除和创建公司/雇员父子关系的索引表
- 2.bulk批量导入json格式数据
- 3.ormapping方式bulk批量导入数据
- 4.采用@ESId指定文档_id
- 5.采用@ESParentId制定子文档的parent信息
- 6.基本的has_child和has_parent公司/雇员父子关系检索
1.准备工作
参考文档《
高性能elasticsearch ORM开发库使用介绍》导入和配置es客户端
2.定义dsl文档
建立dsl配置文件-esmapper/indexparentchild.xml
<properties>
<!--
本案例适用于es 2.x,5.x
创建包含员工类型和公司类型的公司索引表
-->
<property name="createCompanyEmployeeIndice">
<![CDATA[{
"settings": {
"number_of_shards": 6,
"index.refresh_interval": "5s"
},
"mappings": {
"company": { ##公司
"properties": {
"name": {
"type": "text",
"fields": { ##dsl注释 定义精确查找的内部keyword字段
"keyword": {
"type": "keyword"
}
}
},
"city": {
"type": "text",
"fields": { ##dsl注释 定义精确查找的内部keyword字段
"keyword": {
"type": "keyword"
}
}
},
"country": {
"type": "text",
"fields": { ##dsl注释 定义精确查找的内部keyword字段
"keyword": {
"type": "keyword"
}
}
},
"companyId": {
"type": "keyword"
}
}
},
"employee":
{ ##雇员
"_parent": {##定义雇员和公司父子关联关系
"type": "company"
},
"_routing": {
"required": false
},
"properties": {
"name": {
"type": "text",
"fields": { ##dsl注释 定义精确查找的内部keyword字段
"keyword": {
"type": "keyword"
}
}
},
"birthday": {
"type": "date",
"format":"yyyy-MM-dd||epoch_millis"
},
"hobby": {
"type": "text",
"fields": { ##dsl注释 定义精确查找的内部keyword字段
"keyword": {
"type": "keyword"
}
}
},
"companyId": {
"type": "keyword"
},
"employId": {
"type": "keyword"
}
}
}
}
}]]>
</property>
<!--
导入公司信息:
-->
<property name="bulkImportCompanyData">
<![CDATA[
{ "index": { "_id": "london" }}
{ "name": "London Westminster", "city": "London", "country": "UK" ,"companyId":"london"}
{ "index": { "_id": "liverpool" }}
{ "name": "Liverpool Central", "city": "Liverpool", "country": "UK" ,"companyId":"liverpool"}
{ "index": { "_id": "paris" }}
{ "name": "Champs Élysées", "city": "Paris", "country": "France","companyId":"paris" }
]]>
</property>
<!--
导入雇员信息:
-->
<property name="bulkImportEmployeeData">
<![CDATA[
{ "index": { "_id": 1, "parent": "london" }}
{ "name": "Alice Smith", "birthday": "1970-10-24", "hobby": "hiking" ,"companyId":"london","employeeId":1 }
{ "index": { "_id": 2, "parent": "london" }}
{ "name": "Mark Thomas", "birthday": "1982-05-16", "hobby": "diving" ,"companyId":"london","employeeId":2}
{ "index": { "_id": 3, "parent": "liverpool" }}
{ "name": "Barry Smith", "birthday": "1979-04-01", "hobby": "hiking" ,"companyId":"liverpool","employeeId":3}
{ "index": { "_id": 4, "parent": "paris" }}
{ "name": "Adrien Grand", "birthday": "1987-05-11", "hobby": "horses" ,"companyId":"paris","employeeId":4}
{ "index": { "_id": 5, "parent": "paris" }}
{ "name": "Adrien Green", "birthday": "1977-05-12", "hobby": "dancing" ,"companyId":"paris","employeeId":5}
]]>
</property>
<!--出生日期为条件检索公司信息-->
<property name="hasChildSearchByBirthday">
<![CDATA[
{
"query": {
"has_child": {
"type": "employee",
"query": {
"range": {
"birthday": {
"gte": #[birthday]
}
}
}
}
}
}
]]>
</property>
<!--姓名为条件检索公司信息-->
<property name="hasChildSearchByName">
<![CDATA[
{
"query": {
"has_child": {
"type": "employee",
"score_mode": "max",
"query": {
"match": {
"name": #[name]
}
}
}
}
}
]]>
</property>
<!--最小员工数为条件检索公司信息-->
<property name="hasChildSearchByMinChild">
<![CDATA[
{
"query": {
"has_child": {
"type": "employee",
"min_children": #[min_children],
"query": {
"match_all": {}
}
}
}
}
]]>
</property>
<!--检索员工信息-->
<property name="hasParentSearchByCountry">
<![CDATA[
{
"query": {
"has_parent": {
"type": "company",
"query": {
"match": {
"country": #[country]
}
}
}
}
}
]]>
</property>
</properties>
3.实现has_child和has_parent检索
首先创建带公司和雇员关系的索引结构
public void createIndice(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
try {
//删除mapping
clientUtil.dropIndice("company");
} catch (ElasticSearchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//创建mapping
clientUtil.createIndiceMapping("company","createCompanyEmployeeIndice");
}
然后通过bulk导入测试需要的公司和雇员数据,本案例通过加载配置文件中的dsl json data导入公司和雇员数据:
public void importData(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
//导入公司数据,并且实时刷新,测试需要,实际环境不要带refresh
clientUtil.executeHttp("company/company/_bulk?refresh","bulkImportCompanyData",ClientUtil.HTTP_POST);
//导入雇员数据,并且实时刷新,测试需要,实际环境不要带refresh
clientUtil.executeHttp("company/employee/_bulk?refresh","bulkImportEmployeeData",ClientUtil.HTTP_POST);
}
如果需要根据List集合批量导入测试数据,则参考以下方法:
/**
* 通过List集合导入雇员和公司数据
*/
public void importDataFromBeans() {
ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
//导入公司数据,并且实时刷新,测试需要,实际环境不要带refresh
List<Company> companies = buildCompanies();
clientUtil.addDocuments("company","company",companies,"refresh");
//导入雇员数据,并且实时刷新,测试需要,实际环境不要带refresh
List<Employee> employees = buildEmployees();
clientUtil.addDocuments("company","employee",employees,"refresh");
}
List<Company>和List<Employee>列表分别对应需要批量导入的公司数据和雇员数据。需要特别说明的是Company和Employee这两个对象采用了注解@ESId来标注文档_id属性,采用@ESParentId属性来标注雇员和公司的关联属性:
public class Company extends ESBaseData {
private String name;
/**
* 将companyId作为索引_id的值
*/
@ESId
private String companyId;
。。。。。。
public class Employee extends ESBaseData {
/**
* 通过ESId注解将employeeId指定为雇员的文档_id
*/
@ESId
private int employeeId;
/**
* 通过ESParentId注解将companyId指定为雇员的parent属性,对应Company中的文档_id的值
*/
@ESParentId
private String companyId;
接下来实现has_child和has_parent检索功能
/**
* 通过雇员生日检索公司信息
*/
public void hasChildSearchByBirthday(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
Map<String,Object> params = new HashMap<String,Object>();
params.put("birthday","1980-01-01");
ESDatas<Company> escompanys = clientUtil.searchList("company/company/_search","hasChildSearchByBirthday",params,Company.class);
List<Company> companyList = escompanys.getDatas();//获取符合条件的公司
long totalSize = escompanys.getTotalSize();
}
/**
* 通过雇员姓名检索公司信息
*/
public void hasChildSearchByName(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
Map<String,Object> params = new HashMap<String,Object>();
params.put("name","Alice Smith");
ESDatas<Company> escompanys = clientUtil.searchList("company/company/_search","hasChildSearchByName",params,Company.class);
List<Company> companyList = escompanys.getDatas();//获取符合条件的公司
long totalSize = escompanys.getTotalSize();
}
/**
* 通过雇员数量检索公司信息
*/
public void hasChildSearchByMinChild(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
Map<String,Object> params = new HashMap<String,Object>();
params.put("min_children",2);
ESDatas<Company> escompanys = clientUtil.searchList("company/company/_search","hasChildSearchByMinChild",params,Company.class);
List<Company> companyList = escompanys.getDatas();//获取符合条件的公司
long totalSize = escompanys.getTotalSize();
}
/**
* 通过公司所在国家检索雇员信息
*/
public void hasParentSearchByCountry(){
ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
Map<String,Object> params = new HashMap<String,Object>();
params.put("country","UK");
ESDatas<Employee> escompanys = clientUtil.searchList("company/employee/_search","hasParentSearchByCountry",params,Employee.class);
List<Employee> companyList = escompanys.getDatas();//获取符合条件的公司
long totalSize = escompanys.getTotalSize();
}
通过junit测试用例执行上述功能
@Test
public void test(){
createIndice();
importData();
hasChildSearchByBirthday();
this.hasChildSearchByName();
this.hasChildSearchByMinChild();
this.hasParentSearchByCountry();
}
4.参考文档
https://blog.csdn.net/napoay/article/details/52032931
https://gitee.com/bboss/elasticsearchdemo/blob/master/src/test/java/org/frameworkset/elasticsearch/parentchild/ParentChildTest.java
https://gitee.com/bboss/elasticsearchdemo/blob/master/src/test/resources/esmapper/indexparentchild.xml
测试用例对应的工程
https://gitee.com/bboss/elasticsearchdemo
5 开发交流
elasticsearch技术交流群:166471282
elasticsearch微信公众号:bbossgroups
分享到:
相关推荐
Elasticsearch in Action 全文检索Elasticsearch in Action 全文检索Elasticsearch in Action 全文检索Elasticsearch in Action 全文检索Elasticsearch in Action 全文检索Elasticsearch in Action 全文检索
ElasticSearch和activiti案例ElasticSearch和activiti案例ElasticSearch和activiti案例ElasticSearch和activiti案例
基于ElasticSearch的海量文本检索系统 基于ElasticSearch的海量文本检索系统,目前支持txt, doc, docx, pdf, ppt格式文本上传及全文查询,本项目作为本人的毕业设计
ElasticSearch分享ppt40页+.pptx 适用于java学习者 作为技术分享也可
Elasticsearch 是一个开源的高度可扩展的全文搜索和分析引擎,拥有查询近实时的超强性能。 大名鼎鼎的Lucene 搜索引擎被广泛用于搜索领域,但是操作复杂繁琐,总是让开发者敬而远之。而 Elasticsearch将 Lucene 作为...
好记性不如烂笔头哦~,ElasticSearch,简称es,es是一个开源的高拓展的分布式全文搜索引擎它可以近乎实时的存储、检索数据;本身拓展性很好,可以拓展到上百台服务器,处理PB级别的数据。es也是用Java开发并使用...
Elasticsearch全文检索,springboot整合ES,包括创建索引,根据id查询,关键字查询,删除索引等基本操作。
elasticsearch-6.2.4 java增删改查操作代码案例,内含elasticsearch-6.2.4 安装包和 java工程,无需依赖maven 直接导入eclipse直接运行,提供非结构化数据的抽取工具类
Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。 Elasticsearch 为所有类型的数据提供近乎实时的...
springboot2+elasticsearch6.4全文检索,整合小例子,文件中包含elasticsearch6.4.zip和可视化包elasticsearch-head-master.zip及springboot整合实例,有单元测试类
基于Springboot + ElasticSearch +Vue+MySQL构建的博客检索系统 项目经过严格测试,确保可以运行! 简易博客检索系统使用前后端分离,前端使用 Vue ,后端使用 SpringBoot 数据库 MySQL 检索使用 ElasticSearch ...
针对elasticsearch的一些研究,我选用的版本是6.12 ,内容包括客户端创建,Mapping分词创建(我这里用的是IK6.12版本),索引创建,条件检索,等,研究中发现,elasticsearch插件必须配套,选用一个版本,如果不同...
ElasticSearch实战 in Action(原著原版)压缩包,ElasticSearch文档,ES全文检索从入门到精通,高清PDF,是学习es和精通es必备手册,能快速达到精通ElasticSearch,一册在手,ElasticSearch无忧,开发、学习、调优...
本科毕业设计+优秀课程设计+大作业+基于Springboot+ElasticSearch构建的博客检索系统(源码+说明设计文档) 本科毕业设计+优秀课程设计+大作业+基于Springboot+ElasticSearch构建的博客检索系统(源码+说明设计文档...
使用spring boot+Elasticsearch 7.9.1+kibana 实现对word,pdf,txt等文件的非结构化数据全文内容检索
网上的学习资料有限,正好我最近在研究es,所以写了一个demo。 springboot集成elasticsearch5.1,支持关键字的拼音和汉字检索。 接口: 1.查询部门树 2.查询产品信息
elasticsearch elasticsearch-6.2.2 elasticsearch-6.2.2.zip 下载
使用ElasticSearch实现全文检索是一种常见且高效的方式。下面是详细的技术实践和说明: 安装和配置ElasticSearch: 首先,需要在服务器上安装ElasticSearch,并确保其正常运行。 然后,进行相关配置,如集群名称、...
Elasticsearch的特性 分布式、全文检索、近实时搜索和分析、高可用、模式自由、restful 讲述Elasticsearch的架构和Elasticsearch 的核心 概念 二、索引数据 单词 文档矩阵,倒排索引,倒排索引实例,单词词典 三、...
elasticsearch_python+flask 检索系统