弹性搜索查询嵌套文档数组

时间:2018-05-17 10:54:09

标签: elasticsearch elasticsearch-5

考虑到我在弹性搜索索引中有一些文档集(在下面提到的结构中)

{
  "xid": "1234567",
  "time": "12/5/12 5:49 AM",
  "data": [
    {
      "id": "abc",
      "amount": 400
    },
    {
     "id": "def",
      "amount": 200 
    }
  ]
}
{
  "xid": "1234568",
  "time": "13/5/12 7:23 AM",
  "data": [
    {
      "id": "abc",
      "amount": 400
    },
    {
     "id": "ghi",
      "amount": 300 
    }
  ]
}

现在在每个文档的数据数组中,我想按ID分组并找到总和。

对于给定的2个文档,解决方案看起来像

{
"id" : "abc",
"total" :800
},
{
"id" : "def",
"total" :200
},
{
"id" : "ghi",
"total" :300
}

请帮我构建我的请求查询。
我的初步方法是

{
  "aggs": {
    "group_by_id": {
      "terms": {
        "field": "data.id.keyword"
      },
      "aggs": {
       "total" : {
         "sum": {
          "field": "data.amount"
        }
       }
      }
    }
  }
}

下面给出了上述查询结果,这不是预期的结果。

{
"id" : "abc",
"total" :1300
},
{
"id" : "def",
"total" :600
},
{
"id" : "ghi",
"total" :700
}

1 个答案:

答案 0 :(得分:1)

您需要使用nested聚合,并且您的字段data的类型应在您的映射中声明为nested

否则Elasticsearch将具有以下文档视图:

{
  "xid": "1234567",
  "time": "12/5/12 5:49 AM",
  "data.id": ["abc", "def"],
  "data.amount": [400, 200]
}

{
  "xid": "1234568",
  "time": "13/5/12 7:23 AM",
  "data.id": ["abc", "ghi"],
  "data.amount": [400, 300]
}

data字段的新映射应如下所示:

"data": {
  "type": "nested",
  "properties": {
    "id": {
      "type": "keyword"
    },
    "amount": {
      "type": "float"
    }
  }
}

现在您可以进行以下聚合:

{
  "size": 0,
  "aggs": {
    "data": {
      "nested": {
        "path": "data"
      },
      "aggs": {
        "group_by_id": {
          "terms": {
            "field": "data.id"
          },
          "aggs": {
            "total": {
              "sum": {
                "field": "data.amount"
              }
            }
          }
        }
      }
    }
  }
}

这是你得到的结果:

"buckets": [
  {
    "key": "abc",
    "doc_count": 2,
    "total": {
      "value": 800
    }
  },
  {
    "key": "def",
    "doc_count": 1,
    "total": {
      "value": 200
    }
  },
  {
    "key": "ghi",
    "doc_count": 1,
    "total": {
      "value": 300
    }
  }
]