要不要再翻翻文档呢?

复杂聚合后计算Others的方法

Elasticsearch | 作者 Tsukiand | 发布于2021年05月25日 | 阅读数:1913

目前遇到一个问题,现在有下面的聚合计算。目的是计算sdkVer的版本分布,然后对device进行唯一值聚合,这样就能得到sdkVer的分布情况(前五名,基于唯一的device来计算的),我们希望只看前5名sdkVer的分布情况,这样的计算是能满足需求的,但是我们还需要看到前五名之外的sdkVer的占据的比例,也就是1 2 3 4 5 Others这六个部分,目前我能想到就是两次聚合,第一次算出前五名的值,第二次排出这前五名的值做聚合来计算。
{
  "size": 0,
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "meetingtime": {
              "from": 1619798400,
              "to": 1621439999,
              "include_lower": true,
              "include_upper": true,
              "time_zone": "UTC",
              "format": "epoch_second",
              "boost": 1.0
            }
          }
        },
        {
          "term": {
            "type": {
              "value": "test",
              "boost": 1.0
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1.0
    }
  },
  "aggregations": {
    "sdkVer": {
      "terms": {
        "field": "sdkVer",
        "size": 5,
        "min_doc_count": 1,
        "shard_min_doc_count": 0,
        "show_term_doc_count_error": false,
        "order": [
          {
            "device": "desc"
          },
          {
            "_key": "asc"
          }
        ]
      },
      "aggregations": {
        "device": {
          "cardinality": {
            "field": "device"
          }
        }
      }
    }
  }
}

不知道是否有方法能一次返回我需要的结果,希望各位给点建议。 谢谢
已邀请:

thewind

赞同来自: w_b Tsukiand

因为 `bucket_script`只能应用于桶聚合的里面,如果可以根据某个特殊字段,只产生一个桶,可以直接使用 `bucket_script`计算出百分比
 
GET yztest/_search
{
"size": 0,
"aggs": {
"a0": {
"terms": {
"field": "f1.keyword"
},
"aggs": {
"a1": {
"terms": {
"field": "sdkVer.keyword",
"size": 5
},
"aggs": {
"a12": {
"cardinality": {
"field": "device.keyword"
}
}
}
},
"a2": {
"sum_bucket": {
"buckets_path": "a1._count" // top5_docs
}
},
"a3": {
"value_count": {
"field": "_id" // total_docs
}
},
"a4": {
"bucket_script": {
"buckets_path": {
"v1": "a2",
"v2": "a3"
},
"script": "(params.v2 - params.v1) / params.v2 * 100" // other_percent
}
}
}
}
}
}
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 9,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "a0" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "1",
          "doc_count" : 9,
          "a1" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 2,
            "buckets" : [
              {
                "key" : "v1.0.0",
                "doc_count" : 3,
                "a12" : {
                  "value" : 3
                }
              },
              {
                "key" : "v2.0.0",
                "doc_count" : 1,
                "a12" : {
                  "value" : 1
                }
              },
              {
                "key" : "v3.0.0",
                "doc_count" : 1,
                "a12" : {
                  "value" : 1
                }
              },
              {
                "key" : "v4.0.0",
                "doc_count" : 1,
                "a12" : {
                  "value" : 1
                }
              },
              {
                "key" : "v5.0.0",
                "doc_count" : 1,
                "a12" : {
                  "value" : 1
                }
              }
            ]
          },
          "a3" : {
            "value" : 9
          },
          "a2" : {
            "value" : 7.0
          },
          "a4" : {
            "value" : 22.22222222222222
          }
        }
      ]
    }
  }
}

thewind

赞同来自:

可以使用管道聚合,求出前 5的 sdkVer 的文档数量(top5_docs),然后根据
other_percent = (total_docs - top5_docs ) / total_docs * 100
 
GET test/_search?track_total_hits=true
{
"size": 0,
"aggs": {
"a1": {
"terms": {
"field": "sdkVer.keyword",
"size": 5
},
"aggs": {
"a12": {
"cardinality": {
"field": "device.keyword"
}
}
}
},
"a2": {
"sum_bucket": {
"buckets_path": "a1._count" //管道聚合
}
}
}
}



{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 9, // total_docs
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "a1" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 2,
      "buckets" : [
        {
          "key" : "v1.0.0",
          "doc_count" : 3,
          "a12" : {
            "value" : 3
          }
        },
        {
          "key" : "v2.0.0",
          "doc_count" : 1,
          "a12" : {
            "value" : 1
          }
        },
        {
          "key" : "v3.0.0",
          "doc_count" : 1,
          "a12" : {
            "value" : 1
          }
        },
        {
          "key" : "v4.0.0",
          "doc_count" : 1,
          "a12" : {
            "value" : 1
          }
        },
        {
          "key" : "v5.0.0",
          "doc_count" : 1,
          "a12" : {
            "value" : 1
          }
        }
      ]
    },
    "a2" : {
      "value" : 7.0 // top5_docs
    }
  }
}

要回复问题请先登录注册