elasticsearch Elasticsearch按下一个/上一个数组项筛选/聚合,elasticsearch,filter,aggregation-framework,bucket,elasticsearch,Filter,Aggregation Framework,Bucket" /> elasticsearch Elasticsearch按下一个/上一个数组项筛选/聚合,elasticsearch,filter,aggregation-framework,bucket,elasticsearch,Filter,Aggregation Framework,Bucket" />

elasticsearch Elasticsearch按下一个/上一个数组项筛选/聚合

elasticsearch Elasticsearch按下一个/上一个数组项筛选/聚合,elasticsearch,filter,aggregation-framework,bucket,elasticsearch,Filter,Aggregation Framework,Bucket,假设三个是这三个文档,需要编写一个elasticsearch查询,该查询获取一个item name参数,并返回它的下一个项(使用顺序计算) itemArray定义为nestedObject,但不必嵌套。我对文档有点迷糊了。任何帮助都将不胜感激 数据示例: { "id" : 0 "itemArray": [ { "name":"X", "order" : 0 }, { "name":"Y", "o

假设三个是这三个文档,需要编写一个elasticsearch查询,该查询获取一个item name参数,并返回它的下一个项(使用顺序计算)

itemArray定义为nestedObject,但不必嵌套。我对文档有点迷糊了。任何帮助都将不胜感激

数据示例:

{
  "id" : 0
  "itemArray": [
     {
        "name":"X",
        "order" : 0
     },
     {
        "name":"Y",
        "order" : 1
     },
     {
        "name":"Z",
        "order" : 2
     }
  ]
}
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
}
{
    "Z": 2,
    "T": 1
}
响应示例对于输入“Y”有两个文档包含Z一个文档包含T;根据顺序在其数组中的Y之后:

{
    "Y": 3
}
{
    "Z": 2,
    "T": 1
}

弹性搜索版本:<强> 6.2

如果你稍微考虑一下,这是非常可行的。

如何实现“数组中的下一个元素”聚合? 请考虑您的映射如下所示:

PUT nextval
{
  "mappings": {
    "item": {
      "properties": {
        "id": {
          "type": "long"
        },
        "itemArray": {
          "type": "nested",
          "properties": {
            "name": {
              "type": "keyword"
            },
            "nextName": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}
{
  ...,
  "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
            }
          ]
        }
      }
    }
  }
}
在这里,我们显式地存储在
嵌套的
数组的下一个值中。现在让我们插入数据:

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"
              }
            }
          }
        }
      }
    }
  }
}
输出如下所示:

PUT nextval
{
  "mappings": {
    "item": {
      "properties": {
        "id": {
          "type": "long"
        },
        "itemArray": {
          "type": "nested",
          "properties": {
            "name": {
              "type": "keyword"
            },
            "nextName": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}
{
  ...,
  "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
            }
          ]
        }
      }
    }
  }
}
它是如何工作的? 关于嵌套对象,需要了解的一件重要事情是:

每个嵌套对象都作为隐藏的单独文档编制索引

我建议阅读指南,它们提供了很好的解释和示例

因为这些对象是分开的,所以我们会丢失它们在数组中的位置信息。这就是您首先在那里下订单的原因

这就是为什么我们把
nextName
字段放在嵌套对象中:这样对象本身就知道哪个是它的邻居

好的,但是为什么聚合如此复杂呢? 让我们回顾一下。在我们的查询中,基本上有4个要点:

  • 通过
    itemArray.name==X进行查询
  • 一级聚合
  • 二级聚合
  • 三级聚合
  • 问题1)非常明显:我们只需要符合我们要求的文档。2)也很简单:因为
    itemArray
    是一个
    嵌套的
    ,我们只能在
    嵌套的
    上下文中进行聚合

    这个问题很棘手。让我们回到查询的输出:

    {
      ...,
      "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\u count
    为9。为什么是9?因为这是文档中与搜索查询匹配的嵌套对象的数量

    这就是为什么我们需要聚合:从所有项目中只选择那些具有
    itemArray.name==X
    的项目

    其中一个也很简单:只需计算字段
    itemArray.nextName
    的每个项满足多少次

    有更好的方法吗? 可能是的。这取决于您的数据、需求以及更改映射的自由度。例如,如果你只是在探索你的数据,那么数据挖掘的潜力是巨大的


    希望有帮助

    谢谢你的回复,尼古拉。如果有一个条件,像前面的项目必须是“X”和“Y”连续。在这个问题上考虑相同的数据。回答必须是“T:1 Z:2”我们可以有这种类型的查询吗?我试图写一个过滤脚本,但没有得到成功的结果。实际上,在聚合之前无法访问筛选器脚本上的数组项。@GkhnSr我认为,如果您需要两个previous和第三个aggregate,则需要将它们添加到
    itemArray
    中,如下所示:
    {“prevName”:“X”、“name”:“Y”、“nextName”:“Z”}
    ,并使用新条件更新查询和筛选器(
    prevName=X&&name=Y
    )。实际上,我的意思是过滤器可能有多个连续的先前输入。根据您的建议,我需要为每个like(prevName=X,Y)将所有PrevyName设置为。必须有更好的方法来查找具有相同先前路径的项。示例数据:
    “X>Y>Z”,“X>Y>Z”,“X>Y>T”
    按上一个过滤:
    “X>Y”
    预期结果:
    “Z:2,T:1”
    @GkhnSr您可以连接这些ID并查询整个前缀,直到开始:
    [{“name”:“X”},{“prefix”:“X”,“name”“Y”},{“prefix”:“X.Y”,“name”:“Z”}]
    和查询部分:
    prefix=“X.Y”
    。想法保持不变-将需要查询的所有内容放在一个项目中。@GkhnSr如果您能够将ID列表转换为字符串,您可能会受益于.Like
    “prefix”:{“userActions”:“login.selectItem.putensit.checkOut”}