假设有三个是这三个文档,需要编写一个 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 ;根据顺序在数组中 Y 之后:
{
"Z": 2,
"T": 1
}
ElasticSearch版本: 6.2
答案 0 :(得分:0)
如果你稍微考虑denormalizing your data,这是非常可行的。
请考虑您的映射如下所示:
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
}
]
}
}
}
}
}
了解嵌套对象的一个重要事项是:
每个嵌套对象都被索引为隐藏的单独文档
我建议阅读指南的this page,它们提供了很好的解释和示例。
由于这些对象是分开的,我们会丢失有关它们在数组中的位置的信息。这就是你把order
置于首位的原因。
这就是为什么我们将nextName
字段放在嵌套对象中:所以对象本身知道哪个是它的邻居。
让我们回顾一下。在我们的查询中,基本上有4个要点:
itemArray.name==X
nested
filter
terms
1)非常明显:我们只想要符合我们要求的文件。 2)也很简单:由于itemArray
是nested
,我们只能在nested
上下文中进行聚合。
3)一个很棘手。让我们回到查询的输出:
{
...,
"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)聚合:从所有项目中只选择那些itemArray.name==X
。
而且一个又简单:只计算每个字段itemArray.nextName
满足的次数。
可能,是的。这取决于您的数据和您的需求以及您有多自由地更改映射。例如,如果您只是在探索数据,scripted aggregations的潜力巨大。
希望有所帮助!