ElasticSearch是一个基于Lucene的开源搜索引擎,支持全文检索,提供restful接口。在ES中,提供了类似于MongoDB的面向文档存储服务,这种面向文档的存储非常灵活,但是文档与文档直接的关联却比较麻烦,MongoDB里面有DBref,ElasticSearch里面却没有这个,这篇文件就简单讲一讲ES的关联查询。
这种类型支持在一个文档中嵌入多个另外类型的文档。
假如说我们需要在一个type里面存储多个人的名字,并且需要把姓和名分开存,这个时候我们
可以这样去定义mapping:
{ "test" : { "properties" : { "users" : { "type" : "nested", "properties": { "first" : {"type": "string" }, "last" : {"type": "string" } } } } } }
首先把type定义成 nested
类型,然后在users下面嵌入mapping的属性。
对嵌入数据的查询可以使用“ .
”进行访问,具体内容可以参考 官网链接 。
使用内嵌的类型唯一不方便的就是对内嵌数据进行插入或者删除操作的时候需要使用Update模块,Update对数据的操作都是通过脚本实现的,个人感觉使用起来不是很方便。为了解决这个问题,我们可以使用新发方法, parent-child
模块。
这个模块支持在插入数据的时候,可以指定一条数据为 parent
,通过这种方式将2条数据关联起来。
首先在定义mapping的时候就需要指定 child
文档需要关联哪个type的 parent
,例如:
{ "user" : { "_parent": { "type": "test" }, "properties": { "first" : {"type": "string" }, "last" : {"type": "string" } } } }
user就是test的 child
然后我们需要在插入 child
数据的时候指定他关联的是具体哪一条 parent
的id,假设我们在test里面有一条数据,id为test_id,那么我们想插入一条 child
数据关联到id为test_id的数据的时候,我们需要这样写:
curl -XPUT localhost:9200/wahaha/user/user_id?parent=test_id -d ' { "first":"wang", "last":"ergou" }'
这里我们插入了一条id为user_id的数据,并且和id为test_id的数据关联。
接下来我们可以通过 child
的属性去查找 parent
:
{ "query": { "has_child": { "type": "user", "query": { "match":{ "last":"ergou" } } } } }
这里我们使用 has_child
方法查找的和last等于二狗的user数据关联的test数据,在 has_child
方法中,我们显式指定了关联的type为user,然后对user进行了一次查询,找到last等于二狗的数据,然后返回这条数据的 parent
。
我们还可以通过 parent
属性去查找 child
:
{ "query": { "has_parent": { "type": "test", "query": { "match":{ "name":"ergou`s father" } } } } }
这里我们使用的是 has_parent
方法,和 has_child
类似,我们先找到二狗他爹这条数据,然后再找到这条数据的 child
,返回结果。
使用parent-child就比内嵌类型灵活很多,对数据的修改不需要使用Update。再提供一个 官网链接