在ElasticSearch中过滤嵌套聚合?

时间:2015-08-21 03:47:50

标签: elasticsearch aggregation

我在ElasticSearch中有以下文档列表(分数为nested):

{
    'type': 'typeA',
    'scores': [
       {'type': 'A', 'val': 45},
       {'type': 'A', 'val': 55},
       {'type': 'B', 'val': 65},
    ]
},
{
    'type': 'typeA',
    'scores': [
       {'type': 'A', 'val': 55},
       {'type': 'A', 'val': 50},
       {'type': 'A', 'val': 57},
    ]
},
{
    'type': 'typeB',
    'scores': [
       {'type': 'B', 'val': 40},
       {'type': 'A', 'val': 50},
       {'type': 'A', 'val': 60},
    ]
}

是否可以让查询返回每type的平均分数,但仅当scores.type为“A”时?

解释(如果我手动完成):

1)仅过滤“A”分数(简化):

{'type': 'typeA', 'scores': [45, 55]},
{'type': 'typeA', 'scores': [55, 50, 57]},
{'type': 'typeB', 'scores': [50, 60]},

2)找到每个文件的AVG:

{'type': 'typeA', 'avg': 50}, // (45+55) / 2
{'type': 'typeA', 'avg': 54}, // (55+50+57) / 3
{'type': 'typeB', 'avg': 55}, // (50 + 60) / 2

3)每种类型的最终聚合:

'typeA' : 52, // (50+54) / 2
'typeB': 55, // (55) / 1

是否有可能或者我应该坚持客户端?

1 个答案:

答案 0 :(得分:1)

是的,绝对可以使用termsnestedavg聚合的组合来实现,如下所示:

{
  "size": 0,
  "aggs": {
    "top_level_type": {                    <---- group by top-level type
      "terms": {
        "field": "type"
      },
      "aggs": {
        "nest": {
          "nested": {                      <---- "dive" your nested scores
            "path": "scores"
          },
          "aggs": {
            "type_filter": {
              "filter": {                  <---- filter only score type A
                "term": {
                  "scores.type": "A"
                }
              },
              "aggs": {
                "average": {
                  "avg": {                 <---- compute the average of the score values
                    "field": "scores.val"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

结果值如下所示:

{
  ...
  "aggregations" : {
    "top_level_type" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [ {
        "key" : "typea",
        "doc_count" : 2,
        "nest" : {
          "doc_count" : 6,
          "type_filter" : {
            "doc_count" : 5,
            "average" : {
              "value" : 52.4
            }
          }
        }
      }, {
        "key" : "typeb",
        "doc_count" : 1,
        "nest" : {
          "doc_count" : 3,
          "type_filter" : {
            "doc_count" : 2,
            "average" : {
              "value" : 55.0
            }
          }
        }
      } ]
    }
  }
}