elasticsearch汇总条件对象列表

时间:2019-05-28 14:35:49

标签: elasticsearch elasticsearch-aggregation

假设我们在Elasticsearch中有以下文档:

[{
  "person": {
    'name': 'asqar'
  },
  "bill": [
    {
      code:2,
      value: 210
    },
    {
      code:3,
      value: 330
    },
    {
      code:8,
      value: 220
    },
  ]
},
{
  "person": {
    'name': 'asqar'
  },
  "bill": [
    {
      code:2,
      value: 340
    },
    {
      code:4,
      value: 340
    },
    {
      code:1,
      value: 200
    },
  ]
},
{
  "person": {
    'name': 'asqar'
  },
  "bill": [
    {
      code:2,
      value: 810
    },
    {
      code:4,
      value: 630
    },
    {
      code:8,
      value: 220
    },
  ]
}]

我希望在某些情况下将聚合函数应用于bill数组中的特定对象,例如,我要计算avg的{​​{1}},其代码为2。

2 个答案:

答案 0 :(得分:2)

需要将现场帐单创建为nested对象以对其进行过滤。

然后您可以使用filter聚合

映射:

PUT testindex/_mapping
{
  "properties": {
    "person": {
      "properties": {
        "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    },
    "bill": {
      "type": "nested",
      "properties": {
        "code": {
          "type": "integer"
        },
        "value":{
          "type": "double"
        }
      }
    }
  }
}

数据:

    "hits" : [
      {
        "_index" : "testindex",
        "_type" : "_doc",
        "_id" : "422tAWsBd-1D6Ztt1_Tb",
        "_score" : 1.0,
        "_source" : {
          "person" : {
            "name" : "asqar"
          },
          "bill" : [
            {
              "code" : 2,
              "value" : 210
            },
            {
              "code" : 3,
              "value" : 330
            },
            {
              "code" : 8,
              "value" : 220
            }
          ]
        }
      },
      {
        "_index" : "testindex",
        "_type" : "_doc",
        "_id" : "5G2uAWsBd-1D6ZttpfR9",
        "_score" : 1.0,
        "_source" : {
          "person" : {
            "name" : "asqar"
          },
          "bill" : [
            {
              "code" : 2,
              "value" : 340
            },
            {
              "code" : 4,
              "value" : 340
            },
            {
              "code" : 1,
              "value" : 200
            }
          ]
        }
      },
      {
        "_index" : "testindex",
        "_type" : "_doc",
        "_id" : "5W2vAWsBd-1D6ZttQfQ_",
        "_score" : 1.0,
        "_source" : {
          "person" : {
            "name" : "asqar"
          },
          "bill" : [
            {
              "code" : 2,
              "value" : 810
            },
            {
              "code" : 4,
              "value" : 630
            },
            {
              "code" : 8,
              "value" : 220
            }
          ]
        }
      }
    ]

查询:

GET testindex/_search
{
  "size": 0, 
  "aggs": {
    "terms_agg": {
      "terms": {
        "field": "person.name.keyword"
      },
      "aggs": {
        "bill": {
          "nested": {
            "path": "bill"
          },
          "aggs": {
            "bill_code": {
              "filter": {
                "term": {
                  "bill.code": 2
                }
              },
              "aggs": {
                "average": {
                  "avg": {
                    "field": "bill.value"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

输出:

 "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "terms_agg" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "asqar",
          "doc_count" : 3,
          "bill" : {
            "doc_count" : 9,
            "bill_code" : {
              "doc_count" : 3,
              "average" : {
                "value" : 453.3333333333333
              }
            }
          }
        }
      ]
    }
  }

答案 1 :(得分:1)

您首先需要确保bill字段是nested类型。然后,您可以使用nested aggregation处理嵌套文档。您可以在bill.code上使用术语聚合,并在字段avg上使用子bill.value聚合来使用此术语聚合。这将为您提供每个代码的平均值。现在,由于只希望针对代码2进行聚合,因此可以使用bucket selector聚合来过滤并仅获取包含代码2的存储桶。

因此最终的汇总查询将如下所示:

{
  "aggs": {
    "VALUE_NESTED": {
      "nested": {
        "path": "bill"
      },
      "aggs": {
        "VALUE_TERM": {
          "terms": {
            "field": "bill.code"
          },
          "aggs": {
            "VALUE_AVG": {
              "avg": {
                "field": "bill.value"
              }
            },
            "CODE": {
              "max": {
                "field": "bill.code"
              }
            },
            "CODE_FILTER": {
              "bucket_selector": {
                "buckets_path": {
                  "code": "CODE"
                },
                "script": "params.code == 2"
              }
            }
          }
        }
      }
    }
  }
}

上面的样本o / p:

"aggregations": {
  "VALUE_NESTED": {
    "doc_count": 9,
    "VALUE_TERM": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 2,
          "doc_count": 3,
          "CODE": {
            "value": 2
          },
          "VALUE_AVG": {
            "value": 453.3333333333333
          }
        }
      ]
    }
  }
}