Elasticsearch filter/aggregation by next/previous 数组项
Elasticsearch filter/aggregation by next/previous array item
假设三个是这三个文档,需要编写一个 elasticsearch 查询,该查询获取项目名称参数和 returns 下一个项目(使用顺序计算)它的出现。
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;在 Y 之后按照顺序在其数组中:
{
"Z": 2,
"T": 1
}
ElasticSearch 版本:6.2
稍微考虑一下denormalizing your data还是比较可行的
如何实现"next element in array"聚合?
考虑一下您的映射如下所示:
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
}
]
}
}
}
}
}
它是如何工作的?
关于嵌套对象需要了解的一件重要事情是:
each nested object is indexed as a hidden separate document
我建议阅读指南的 this page,它们提供了很好的解释和示例。
由于这些对象是分开的,我们失去了关于它们在数组中的位置的信息。这就是您首先将 order
放在那里的原因。
这就是我们将 nextName
字段放在嵌套对象中的原因:因此对象本身知道哪个是它的邻居。
好的,但为什么聚合如此复杂?
让我们回顾一下。在我们的查询中,基本上有 4 个要点:
1) 很明显:我们只需要符合我们要求的文件。 2) 也很简单:因为 itemArray
是 nested
,我们只能在 nested
上下文中进行聚合。
3) 一个很棘手。让我们return到查询的输出:
{
...,
"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?因为这是我们在与搜索查询匹配的文档中拥有的嵌套对象的数量。
这就是我们需要 3) 聚合的原因:从所有项目 select 中,只有那些具有 itemArray.name==X
.
的项目
而 4) 也很简单:只需计算每个字段 itemArray.nextName
被满足的次数。
有没有更好的方法?
可能是的。这取决于您的数据和您的需求以及您更改映射的自由程度。例如,如果您只是探索数据,scripted aggregations 的潜力是巨大的。
希望对您有所帮助!
假设三个是这三个文档,需要编写一个 elasticsearch 查询,该查询获取项目名称参数和 returns 下一个项目(使用顺序计算)它的出现。
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;在 Y 之后按照顺序在其数组中:
{
"Z": 2,
"T": 1
}
ElasticSearch 版本:6.2
稍微考虑一下denormalizing your data还是比较可行的
如何实现"next element in array"聚合?
考虑一下您的映射如下所示:
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
}
]
}
}
}
}
}
它是如何工作的?
关于嵌套对象需要了解的一件重要事情是:
each nested object is indexed as a hidden separate document
我建议阅读指南的 this page,它们提供了很好的解释和示例。
由于这些对象是分开的,我们失去了关于它们在数组中的位置的信息。这就是您首先将 order
放在那里的原因。
这就是我们将 nextName
字段放在嵌套对象中的原因:因此对象本身知道哪个是它的邻居。
好的,但为什么聚合如此复杂?
让我们回顾一下。在我们的查询中,基本上有 4 个要点:
1) 很明显:我们只需要符合我们要求的文件。 2) 也很简单:因为 itemArray
是 nested
,我们只能在 nested
上下文中进行聚合。
3) 一个很棘手。让我们return到查询的输出:
{
...,
"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?因为这是我们在与搜索查询匹配的文档中拥有的嵌套对象的数量。
这就是我们需要 3) 聚合的原因:从所有项目 select 中,只有那些具有 itemArray.name==X
.
而 4) 也很简单:只需计算每个字段 itemArray.nextName
被满足的次数。
有没有更好的方法?
可能是的。这取决于您的数据和您的需求以及您更改映射的自由程度。例如,如果您只是探索数据,scripted aggregations 的潜力是巨大的。
希望对您有所帮助!