假设这三个文档是这三个文档,需要编写一个elasticsearch查询,该查询获取一个项名参数,并在出现的情况下返回下一个项(使用顺序计算)。
itemArray被定义为nestedObject,但不需要嵌套。我有点迷上文件了。任何帮助都将不胜感激。
数据示例:
doc-1
{
"id" : 0
"itemArray": [
{
"name":"X",
"order" : 0
},
{
"name":"Y",
"order" : 1
},
{
"name":"Z",
"order" : 2
}
]
}doc-2
{
"id" : 1
"itemArray": [
{
"name":"X",
"order" : 0
},
{
"name":"Y",
"order" : 1
},
{
"name":"T",
"order" : 2
}
]
}doc-3
{
"id" : 2
"itemArray": [
{
"name":"X",
"order" : 0
},
{
"name":"Y",
"order" : 1
},
{
"name":"Z",
"order" : 2
}
]
}响应示例用于输入"X",有三个文档包含Y;在其数组中按照顺序排列X之后:
{
"Y": 3
}响应示例用于输入"Y“有两个文档包含Z和一个文档包含T;在YE 231之后,按顺序排列在其数组中:
{
"Z": 2,
"T": 1
}ElasticSearch版本:6.2
发布于 2018-04-03 21:49:12
如果您考虑一下去角色化数据,这是非常可行的。
如何实现“数组中的下一个元素”聚合?
考虑一下,您的映射应该如下所示:
PUT nextval
{
"mappings": {
"item": {
"properties": {
"id": {
"type": "long"
},
"itemArray": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"nextName": {
"type": "keyword"
}
}
}
}
}
}
}在这里,我们显式地存储在数组的nested下一个值中。现在让我们插入数据:
POST nextval/item/0
{
"id" : 0,
"itemArray": [
{
"name":"X",
"nextName":"Y"
},
{
"name":"Y",
"nextName":"Z"
},
{
"name":"Z"
}
]
}
POST nextval/item/1
{
"id" : 1,
"itemArray": [
{
"name":"X",
"nextName":"Y"
},
{
"name":"Y",
"nextName":"T"
},
{
"name":"T"
}
]
}
POST nextval/item/2
{
"id" : 2,
"itemArray": [
{
"name":"X",
"nextName":"Y"
},
{
"name":"Y",
"nextName":"Z"
},
{
"name":"Z"
}
]
}并使用这样的查询来获得输入X的结果
POST nextval/item/_search
{
"query": {
"nested": {
"path": "itemArray",
"query": {
"term": {
"itemArray.name": "X"
}
}
}
},
"aggs": {
"1. setup nested": {
"nested": {
"path": "itemArray"
},
"aggs": {
"2. filter agg results": {
"filter": {
"term": {
"itemArray.name": "X"
}
},
"aggs": {
"3. aggregate by nextName": {
"terms": {
"field": "itemArray.nextName"
}
}
}
}
}
}
}
}输出将如下所示:
{
...,
"aggregations": {
"1. setup nested": {
"doc_count": 9,
"2. filter agg results": {
"doc_count": 3,
"3. aggregate by nextName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Y",
"doc_count": 3
}
]
}
}
}
}
}如果我们对输入Y执行查询,输出将是:
{
...,
"aggregations": {
"1. setup nested": {
"doc_count": 9,
"2. filter agg results": {
"doc_count": 3,
"3. aggregate by nextName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Z",
"doc_count": 2
},
{
"key": "T",
"doc_count": 1
}
]
}
}
}
}
}它怎麽工作?
关于嵌套对象,需要了解的一件重要事情是:
每个嵌套对象都被索引为一个隐藏的单独文档。
我推荐阅读指南的此页,它们提供了很好的解释和例子。
因为这些对象是分开的,所以我们失去了关于它们在数组中的位置的信息。这就是你把order放在第一位的原因。
这就是为什么我们将nextName字段放在嵌套对象中的原因:因此对象本身知道哪个是它的邻居。
好吧,但是为什么聚合如此复杂呢?
让我们重温一下。在我们的查询中,基本上有四个要点:
这是相当明显的:我们只需要与我们的请求相对应的文档。2)也很简单:因为itemArray是nested,所以我们只能在nested上下文中进行聚合。
其中一个很棘手。让我们返回到查询的输出:
{
...,
"aggregations": {
"1. setup nested": {
"doc_count": 9,
"2. filter agg results": {
"doc_count": 3,
"3. aggregate by nextName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Z",
"doc_count": 2
},
{
"key": "T",
"doc_count": 1
}
]
}
}
}
}
}第一个聚合的doc_count是9,为什么是9?因为这是与搜索查询匹配的文档中嵌套对象的数量。
这就是为什么我们需要聚合:从所有项中只选择那些有itemArray.name==X的。
其中一个同样很简单:只需计算字段itemArray.nextName的每个项满足多少次即可。
有没有更好的方法?
可能是的。这取决于您的数据和您的需求,以及您是否可以自由地更改映射。例如,如果您只是在探索您的数据,那么脚本聚合的潜力是巨大的。
希望这能帮上忙!
https://stackoverflow.com/questions/49628926
复制相似问题