文档章节

Elasticsearch 父子关系维护和检索案例分享

bboss
 bboss
发布于 2018/04/10 15:15
字数 1504
阅读 982
收藏 5

Elasticsearch 父子关系维护和检索案例分享,展示has_child和has_parent的基本用法。 

本案例针对elasticsearch 5.x进行父子关系进行介绍,6.x版本通过join type来实现父子关系检索,参考文档后面提供的demo

本文涉及技术点: 

  • 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>列表分别对应需要批量导入的公司数据和雇员数据。需要特别说明的是CompanyEmployee这两个对象采用了注解@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.参考文档

5.x父子查询示例:
https://gitee.com/bbossgroups/eshelloword-booter/tree/master/src/test/java/org/bboss/elasticsearchtest/parentchild
6.x父子查询示例:
https://gitee.com/bbossgroups/eshelloword-booter/tree/master/src/test/java/org/bboss/elasticsearchtest/jointype

https://blog.csdn.net/napoay/article/details/52032931

测试用例对应的工程

https://gitee.com/bbossgroups/eshelloword-booter

 

© 著作权归作者所有

共有 人打赏支持
bboss

bboss

粉丝 110
博文 60
码字总数 68205
作品 8
长沙
程序员
私信 提问
ES(elasticsearch)搜索引擎

ES(elasticsearch)搜索引擎 0、授人以渔,少走半年弯路! 死磕 Elasticsearch 方法论:普通程序员高效精进的 10 大狠招! 一、Elasitcsearch基础篇 1.1 Elasitcsearch基础认知 1、Elasticse...

Ocean_K
2018/09/11
0
0
Elasticsearch简介与实战

什么是Elasticsearch?   Elasticsearch是一个开源的分布式、RESTful 风格的搜索和数据分析引擎,它的底层是开源库Apache Lucene。   Lucene 可以说是当下最先进、高性能、全功能的搜索引...

但盼风雨来_jc
03/06
0
0
Elasticsearch最佳实践之使用场景

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zwgdft/article/details/82917861 序   最开始使用Elasticsearch是两年多前,在一家创业公司负责数据系统的...

Mr-Bruce
2018/10/08
0
0
基于 elasticsearch 的网站数据全文检索

【业务需求】 一、功能需求 网站需要向用户提供基于elasticsearch的全文检索功能支持,包括: 1、通过关键字词检索符合用户期望的数据,结合数据匹配度向用户数据 list; 2、良好实现中文、英...

network2019
2017/08/10
0
0
bboss v5.2.1 发布,Elasticsearch Rest Client

The best Elasticsearch Highlevel Rest Client API-----bboss v5.2.1 发布。 主要功能特色 ElasticSearch兼容性:2.x,5.x,6.x,+ JDK兼容性: jdk 1.7+ Spring boot兼容性:1.x,2.x ORM和DSL二......

bboss
2018/11/27
455
2

没有更多内容

加载失败,请刷新页面

加载更多

一文纵览EMAS 到底内含多少阿里核心技术能力

EMAS的整体定位是阿里巴巴移动技术对外输出的主窗口,沉淀了阿里巴巴近10年在移动互联网技术架构上的积累以及在一系列垂直场景中所实践的核心技术能力。一方面,EMAS希望为广大开发者提供安全...

阿里云官方博客
26分钟前
1
0
Prometheus简介

Prometheus是什么? Prometheus(普罗米修斯)是一套最初在SoundCloud上构建的开源监视和告警系统 。 特征 普罗米修斯的主要特点是: 具有由度量名称和键/值对标识的时间序列数据的多维数据模...

阿dai学长
50分钟前
1
0
“阿里巴巴小程序繁星计划”:20亿扶持200万小程序开发者和100万商家

3月21日,在2019阿里云峰会·北京站上,阿里巴巴旗下的阿里云、支付宝、淘宝、钉钉、高德等联合发布“阿里巴巴小程序繁星计划”:提供20亿元补贴,扶持200万+小程序开发者、100万+商家。凡入...

阿里云云栖社区
今天
6
0
Android 动画Animation

动画分为视图动画(view animation)和属性动画(property animation),视图动画又分为帧动画和补间动画 视图动画控件(iv)点击事件(OnClickListener接口)触发位置在原位置 1.帧动画(Fra...

Coding缘
今天
1
0
Mysql-常用日期查询

今天: SELECT * FROM A WHERE create_time = create_time(now()); 昨天: SELECT * FROM A WHERE TO_DAYS( NOW( ) ) - TO_DAYS( create_time) <= 1; 最近7天: SELECT * FROM A where DATE......

米饭有毒
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部