Elasticsearch返回父子数据关联查询案例

在《 Elasticsearch 父子关系维护和检索案例分享》一文中介绍了Elasticsearch 父子关系维护和检索的基本功能,本文接着上篇文档,分享同时返回父子数据Elasticsearch 关联查询案例。

本文涉及到的技术点:
  • inner_hits的使用,通过inner_hits来同时返回父表数据和子表数据
  • 父子双向数据检索及结果绑定和遍历

1.准备工作
参考文档《 高性能elasticsearch ORM开发库使用介绍》导入和配置es客户端

2.定义带inner_hits的dsl检索语句
在dsl配置文件-esmapper/indexparentchild.xml中增加两个dsl检索语句:

hasChildSearchReturnParent2ndChildren 演示在按照雇员信息检索公司数据时,同时返回符合条件的公司下面的员工信息

hasParentSearchByCountryReturnParent2ndChildren 演示在按照公司信息检索雇员数据时,同时返回符合条件的雇员对应的公司信息
    <!--以雇员姓名为条件检索公司信息并返回公司雇员信息-->
    <property name="hasChildSearchReturnParent2ndChildren">
        <![CDATA[
            {
              "query": {
                "has_child": {
                  "type":       "employee",
                  "score_mode": "max",
                  "query": {
                    "match": {
                      "name": #[name] ##雇员名称参数
                    }
                  },
                  "inner_hits": {} ## 这是同时返回父子数据的关键所在
                }
              }
            }
        ]]>
    </property>
    <!--根据公司所在的国家信息检索员工信息,同时返回员工所属的公司信息-->
    <property name="hasParentSearchByCountryReturnParent2ndChildren">
        <![CDATA[
            {
              "query": {
                "has_parent": {
                  "type": "company",
                  "query": {
                    "match": {
                      "country": #[country] ##国家代码参数
                    }
                  },
                  "inner_hits": {} ## 这是同时返回父子数据的关键所在
                }
              }
            }
        ]]>
    </property>

3.定义检索操作方法
在文件 ParentChildTest.java中增加以下方法


	/**
	 * 检索公司信息,并返回公司对应的雇员信息(符合检索条件的雇员信息)
	 */
	public void hasChildSearchReturnParent2ndChildren(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("name","Alice Smith");

		try {
			ESInnerHitSerialThreadLocal.setESInnerTypeReferences(Employee.class);//指定inner查询结果对于雇员类型
			ESDatas<Company> escompanys = clientUtil.searchList("company/company/_search","hasChildSearchReturnParent2ndChildren",params,Company.class);
			long totalSize = escompanys.getTotalSize();
			List<Company> companyList = escompanys.getDatas();//获取符合条件的公司
			//查看公司下面的雇员信息(符合检索条件的雇员信息)
			for (int i = 0; i < companyList.size(); i++) {
				Company company = companyList.get(i);
				List<Employee> employees = ResultUtil.getInnerHits(company.getInnerHits(), "employee");
				System.out.println(employees.size());
			}
		}
		finally{
			ESInnerHitSerialThreadLocal.clean();//清空inner查询结果对于雇员类型
		}
	}
	/**
	 * 通过公司所在国家检索雇员信息,并返回雇员对应的公司信息
	 */
	public void hasParentSearchByCountryReturnParent2ndChildren(){

		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/indexparentchild.xml");
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("country","UK");

		try {
			ESInnerHitSerialThreadLocal.setESInnerTypeReferences(Company.class);//指定inner查询结果对于公司类型
			ESDatas<Employee> escompanys = clientUtil.searchList("company/employee/_search","hasParentSearchByCountryReturnParent2ndChildren",params,Employee.class);
			List<Employee> employeeList = escompanys.getDatas();//获取符合条件的雇员数据
			long totalSize = escompanys.getTotalSize();
			//查看每个雇员对应的公司信息
			for(int i = 0;  i < employeeList.size(); i ++) {
				Employee employee = employeeList.get(i);
				List<Company> companies = ResultUtil.getInnerHits(employee.getInnerHits(), "company");
				System.out.println(companies.size());
			}
		}
		finally{
			ESInnerHitSerialThreadLocal.clean();//清空inner查询结果对于公司类型
		}
	}

说明:

1) 通过ESInnerHitSerialThreadLocal指定了inner_hits中需要返回的数据对象类型

ESInnerHitSerialThreadLocal.setESInnerTypeReferences(Employee.class);//指定inner查询结果对于雇员类型
ESInnerHitSerialThreadLocal.setESInnerTypeReferences(Company.class);//指定inner查询结果对于公司类型
使用后需要清除:

ESInnerHitSerialThreadLocal.clean();//清空inner查询结果对于雇员类型
2) employee.getInnerHits()和company.getInnerHits()方法都是从ESBaseData继承的方法,bboss会自动将inner_hits检索到的父子关联数据设置到ESBaseData对象中,可以通过getInnerHits()方法获取到对应的数据;

3) ResultUtil.getInnerHits工具方法用于获取父/子关联检索对应的子/父的结果,方法的第二个参数对应inner_hits检索的类型和名称:

List<Employee> employees = ResultUtil.getInnerHits(company.getInnerHits(), "employee");       

List<Company> companies = ResultUtil.getInnerHits(employee.getInnerHits(), "company");


4.执行测试方法
通过junit,执行新的测试方法

@Test
public void testFromJson(){
   createIndice();
   importFromJsonData();
   hasChildSearchByBirthday();
   this.hasChildSearchByName();
   this.hasChildSearchByMinChild();
   this.hasParentSearchByCountry();

   this.hasChildSearchReturnParent2ndChildren();//本文对应的方法
   this.hasParentSearchByCountryReturnParent2ndChildren();//本文对应的方法
}

5.参考文档
https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-inner-hits.html#nested-inner-hits

6.开发交流
elasticsearch技术交流群:166471282

elasticsearch微信公众号:bbossgroups
img_a21db47cf20ac4820026d60bcb2b9470.jpe
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值