ElasticSearch是一个基于Lucene的开源搜索引擎,支持全文检索,提供restful接口。在ES中,提供了类似于MongoDB的面向文档存储服务,这种面向文档的存储非常灵活,但是文档与文档直接的关联却比较麻烦,MongoDB里面有DBref,ElasticSearch里面却没有这个,这篇文章就简单讲一讲ES的关联查询。
使用nested:
这种类型支持在一个文档中嵌入多个另外类型的文档。
假如说我们需要在一个type里面存储多个人的名字,并且需要把姓和名分开存,这个时候我们
可以这样去定义mapping:
{
"test" : {
"properties" : {
"users" : {
"type" : "nested",
"properties": {
"first" : {"type": "string" },
"last" : {"type": "string" }
}
}
}
}
}
首先把type定义成nested
类型,然后在users下面嵌入mapping的属性。
对嵌入数据的查询可以使用“.
”进行访问,具体内容可以参考官网链接。
使用内嵌的类型的优势在于一次查询,本身的文档和内嵌的文档一起返回。唯一不方便的就是对内嵌数据进行插入或者删除操作的时候需要使用Update模块,Update对数据的操作都是通过脚本实现的,个人感觉使用起来不是很方便。为了解决这个问题,我们可以使用新方法,parent-child
模块。
使用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。,可以根据parent查child,也可以根据child查parent,如果需要返回2种文档就需要使用聚合。