es内嵌文档查询_Elasticsearch中的嵌套查询介绍及实例

本文介绍了Elasticsearch中解决嵌套数据结构交叉匹配问题的nested对象,阐述了nested对象如何保持子文档关联性,并通过实例展示了nested查询的使用方法。同时,提到了nested查询的性能和操作代价,包括全量索引更新和检索结果的返回策略。
摘要由CSDN通过智能技术生成

大家在工作中想必也接触过Elasticsearch,今天介绍一下es中的嵌套对象及对应的查询方式。

从考虑一个业务场景开始吧,业务上需要把某些类似的商品聚合成为一个关联组,需要支持根据某个商品的特征,查询到它所在的关联组,es中的存储结构如下:

{

"memberGoods":[

{

"title":"商品A",

"brand":"a"

},

{

"title":"商品B",

"brand":"b"

}

],

"groupId":"A"

}

那么问题来了,如果memberGoods是一个普通的Object类型,对于下面的查询条件:

{

"query":{

"bool":{

"must":[

{

"match":{

"title":"商品A"

}

},

{

"match":{

"brand":"b"

}

}

]

}

}

}

上面的数据依然会匹配上,但是商品A的品牌应该是a,而不是b呀,造成这种现象的原因是结构性的JSON文档会平整成索引内的一个简单键值格式,就像这样:

{

"memberGoods.title":[

"商品A",

"商品B"

],

"memberGoods.brand":[

"a",

"b"

],

"groupId":"A"

}

显然,如上的数据损失了同一商品数据之间的关联性,从而出现了交叉匹配的现象,为解决这一问题,nested Object应运而生,它保留了子文档数据中的关联性,如果memberGoods的数据格式被定义为nested,那么每一个nested object 将会作为一个隐藏的单独文本建立索引。如下:

{

"groupId":"A"

},

{

"memberGoods.title":"商品A",

"memberGoods.brand":"a"

},

{

"memberGoods.title":"商品B",

"memberGoods.brand":"b"

}

通过分开给每个nested object建索引,object内部的字段间的关系就能保持。当执行查询时,只会匹配’match’同时出现在相同的nested object的结果。

不仅如此,由于nested objects 建索引的方式,在查询的时候将根文本和nested文档拼接是很快的,就跟把他们当成一个单独的文本一样的快。

nested object作为一个独立隐藏文档单独建索引,因此,我们不能直接查询它们。取而代之,我们必须使用nested查询或者nested filter来接触它们,java语言描述如下:

queryBuilder.must(QueryBuilders.nestedQuery("memberGoods"/** nested 字段*/,

QueryBuilders.matchPhraseQuery("memberGoods.title", "商品A"), ScoreMode.Avg));

其中memberGoods是父字段,memberGoods.title是子字段,以上已有提及,最后的参数ScoreMode.Avg是父文档匹配分数的设定,(Parent hit's score is the average/max/sum/min of all child scores.)

此外,nested形式的查询也有一些需要注意的缺点:

1.增加,改变或者删除一个nested文本,整个文本必须重新建索引。nested文本越多,代价越大。

2.检索请求会返回整个文本,而不仅是匹配的nested文本。尽管有计划正在执行以能够支持返回根文本的同时返回最匹配的nested文本,但目前还未实现。

--------------------------------------------

更多详细内容,请参考es官方文档:

https://www.elastic.co/guide/en/elasticsearch/guide/master/nested-objects.html

https://www.elastic.co/guide/en/elasticsearch/guide/master/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值