即使是不成熟的尝试,也胜于胎死腹中的策略。
sum bucket

sum bucket

关于sum bucket 与Filter Aggregation 结合的写法分享

Elasticsearchcq1988114 发表了文章 • 0 个评论 • 2703 次浏览 • 2019-09-19 00:14 • 来自相关话题

我们可以用ES的桶来实现这样的需求,找出汽车厂商每个颜色的车辆数量 当如果需求是,找出汽车厂商里的车一共有多少种颜色呢?  我们可以使用sum bucket ,默认情况下,可以参考官方文档 https://www.elastic.co/guide/e ... ml%23   但如果我们想找到售价大于100W的车,有多少种颜色呢? 这就需要Filter Aggregation   和 上文的sum bucket结合   这里有个需要注意的地方,sum_bucket的位置不要跟 Filter Aggregation 同级,而是应该在其下一级:
    "query": {
        "query": {
            "bool": {
                "filter": {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "delflag": 0
                                }
                            },
                            {
                                "term": {
                                    "is_child": 1
                                }
                            }
                        ],
                        "must_not": 
                    }
                }
            }
        },
        "aggs": {
            "valid_sales_people": {
                "filter": {
                    "bool": {
                        "must_not": {
                            "terms": {
                                "status": [
                                    0,
                                    1,
                                    7
                                ]
                            }
                        }
                    }
                },
                "aggs": {
                    "render_people": {
                        "terms": {
                            "field": "uid",
                            "size": 2147483647
                        },
                        "aggs": {
                            "unique_people": {
                                "cardinality": {
                                    "field": "uid"
                                }
                            }
                        }
                    },
                    "member_count": {
                        "sum_bucket": {
                            "buckets_path": "render_people>unique_people" 
                        }
                    }
                }
            }
        }
    },
如代码所示,我希望对status not in (0,1,7)的uid(用户)进行聚合,并想得到uid桶种类的求和,那么member_count就应该与render_people同级,而不是把member_count放到和与valid_sales_people同一级。   如果将member_count 与valid_sales_people放到同一级,会报一个错:sum_bucket的第一个聚合必须是多桶聚合。究其原因,应该是加上filter aggregation后,valid_sales_people已不具有多桶聚合属性(因为附带了filter过滤条件),而其下的render_people则具有了多桶聚合属性。所以member_count应该与render_people放在同级,对应的buckets_path也自然改为render_people>unique_people    

记一次“访问量超过1000的人数”统计,计算聚合桶的个数

Elasticsearchziyou 发表了文章 • 2 个评论 • 7615 次浏览 • 2019-08-01 18:45 • 来自相关话题

前言

众所周知,在ES中有各种聚合方法能够是数据分析简单、高效。但是在繁杂的聚合方法中找到满足我们需求的那个,需要我们自己去实践。下面我就说明一下“访问量超过1000的人数”统计案例的实现。

需求

ES在使用过程中,我们公司有一个需求,就是需要统计活跃用户数,我们定义活跃用户数为:今日访问量超过1000的用户,所以我们统计活跃用户数的时候需要统计“访问量超过1000的人数”。

之前的做法

第一版统计活跃用户数的方法由于对复杂的聚合统计不熟悉的原因,就把统计分为了两步。 第一步:在ES中使用字段聚合每个用户的访问数量,数量大于1000;

查询语句

{
  "aggs": {
    "user": {
      "terms": {
        "field": "userId.keyword",
        "size": 10000,
        "order": {
          "_count": "desc"
        },
        "min_doc_count": "1000"
      }
    }
  },
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "startTime": {
              "gte": "now-4h",
              "lte": "now",
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

查询结果

{
  "took" : 203,
  "timed_out" : false,
  "_shards" : {
    "total" : 1565,
    "successful" : 1565,
    "skipped" : 1520,
    "failed" : 0
  },
  "hits" : {
    "total" : 67470,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "user" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "admin",
          "doc_count" : 46998
        },
        {
          "key" : "nameless",
          "doc_count" : 8416
        },
        {
          "key" : "li",
          "doc_count" : 2486
        },
        {
          "key" : "liu",
          "doc_count" : 2183
        },
        {
          "key" : "111111",
          "doc_count" : 1281
        }
      ]
    }
  }
}

第二步:从ES中获取第一步的统计结果,然后统计用户桶的个数,达到统计出个数的效果。

改进后的做法

改进后就是直接使用ES的查询,使用了sum_bucket聚合,是计算每个用户的用户ID独立数,也就是每个用户的用户ID独立数都是1,然后用桶聚合求和,得到所有的人数。 参考链接:[sum bucket聚合](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-pipeline-sum-bucket-aggregation.html)

查询语句

{
  "aggs": {
    "usercount": {
      "sum_bucket": {
        "buckets_path": "usercount-bucket>usercount-metric"
      }
    },
    "usercount-bucket": {
      "terms": {
        "field": "userId.keyword",
        "size": 10,
        "order": {
          "_key": "desc"
        },
        "min_doc_count": "1000"
      },
      "aggs": {
        "usercount-metric": {
          "cardinality": {
            "field": "userId.keyword"
          }
        }
      }
    }
  },
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "x_st": {
              "gte": "now-4h",
              "lte": "now",
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

查询结果

{
  "took" : 106,
  "timed_out" : false,
  "_shards" : {
    "total" : 1565,
    "successful" : 1565,
    "skipped" : 1520,
    "failed" : 0
  },
  "hits" : {
    "total" : 63956,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "usercount-bucket" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "nameless",
          "doc_count" : 8278,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "liu",
          "doc_count" : 2142,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "li",
          "doc_count" : 1928,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "admin",
          "doc_count" : 44395,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "111111",
          "doc_count" : 1281,
          "usercount-metric" : {
            "value" : 1
          }
        }
      ]
    },
    "usercount" : {
      "value" : 5.0
    }
  }
}

关于sum bucket 与Filter Aggregation 结合的写法分享

Elasticsearchcq1988114 发表了文章 • 0 个评论 • 2703 次浏览 • 2019-09-19 00:14 • 来自相关话题

我们可以用ES的桶来实现这样的需求,找出汽车厂商每个颜色的车辆数量 当如果需求是,找出汽车厂商里的车一共有多少种颜色呢?  我们可以使用sum bucket ,默认情况下,可以参考官方文档 https://www.elastic.co/guide/e ... ml%23   但如果我们想找到售价大于100W的车,有多少种颜色呢? 这就需要Filter Aggregation   和 上文的sum bucket结合   这里有个需要注意的地方,sum_bucket的位置不要跟 Filter Aggregation 同级,而是应该在其下一级:
    "query": {
        "query": {
            "bool": {
                "filter": {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "delflag": 0
                                }
                            },
                            {
                                "term": {
                                    "is_child": 1
                                }
                            }
                        ],
                        "must_not": 
                    }
                }
            }
        },
        "aggs": {
            "valid_sales_people": {
                "filter": {
                    "bool": {
                        "must_not": {
                            "terms": {
                                "status": [
                                    0,
                                    1,
                                    7
                                ]
                            }
                        }
                    }
                },
                "aggs": {
                    "render_people": {
                        "terms": {
                            "field": "uid",
                            "size": 2147483647
                        },
                        "aggs": {
                            "unique_people": {
                                "cardinality": {
                                    "field": "uid"
                                }
                            }
                        }
                    },
                    "member_count": {
                        "sum_bucket": {
                            "buckets_path": "render_people>unique_people" 
                        }
                    }
                }
            }
        }
    },
如代码所示,我希望对status not in (0,1,7)的uid(用户)进行聚合,并想得到uid桶种类的求和,那么member_count就应该与render_people同级,而不是把member_count放到和与valid_sales_people同一级。   如果将member_count 与valid_sales_people放到同一级,会报一个错:sum_bucket的第一个聚合必须是多桶聚合。究其原因,应该是加上filter aggregation后,valid_sales_people已不具有多桶聚合属性(因为附带了filter过滤条件),而其下的render_people则具有了多桶聚合属性。所以member_count应该与render_people放在同级,对应的buckets_path也自然改为render_people>unique_people    

记一次“访问量超过1000的人数”统计,计算聚合桶的个数

Elasticsearchziyou 发表了文章 • 2 个评论 • 7615 次浏览 • 2019-08-01 18:45 • 来自相关话题

前言

众所周知,在ES中有各种聚合方法能够是数据分析简单、高效。但是在繁杂的聚合方法中找到满足我们需求的那个,需要我们自己去实践。下面我就说明一下“访问量超过1000的人数”统计案例的实现。

需求

ES在使用过程中,我们公司有一个需求,就是需要统计活跃用户数,我们定义活跃用户数为:今日访问量超过1000的用户,所以我们统计活跃用户数的时候需要统计“访问量超过1000的人数”。

之前的做法

第一版统计活跃用户数的方法由于对复杂的聚合统计不熟悉的原因,就把统计分为了两步。 第一步:在ES中使用字段聚合每个用户的访问数量,数量大于1000;

查询语句

{
  "aggs": {
    "user": {
      "terms": {
        "field": "userId.keyword",
        "size": 10000,
        "order": {
          "_count": "desc"
        },
        "min_doc_count": "1000"
      }
    }
  },
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "startTime": {
              "gte": "now-4h",
              "lte": "now",
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

查询结果

{
  "took" : 203,
  "timed_out" : false,
  "_shards" : {
    "total" : 1565,
    "successful" : 1565,
    "skipped" : 1520,
    "failed" : 0
  },
  "hits" : {
    "total" : 67470,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "user" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "admin",
          "doc_count" : 46998
        },
        {
          "key" : "nameless",
          "doc_count" : 8416
        },
        {
          "key" : "li",
          "doc_count" : 2486
        },
        {
          "key" : "liu",
          "doc_count" : 2183
        },
        {
          "key" : "111111",
          "doc_count" : 1281
        }
      ]
    }
  }
}

第二步:从ES中获取第一步的统计结果,然后统计用户桶的个数,达到统计出个数的效果。

改进后的做法

改进后就是直接使用ES的查询,使用了sum_bucket聚合,是计算每个用户的用户ID独立数,也就是每个用户的用户ID独立数都是1,然后用桶聚合求和,得到所有的人数。 参考链接:[sum bucket聚合](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-pipeline-sum-bucket-aggregation.html)

查询语句

{
  "aggs": {
    "usercount": {
      "sum_bucket": {
        "buckets_path": "usercount-bucket>usercount-metric"
      }
    },
    "usercount-bucket": {
      "terms": {
        "field": "userId.keyword",
        "size": 10,
        "order": {
          "_key": "desc"
        },
        "min_doc_count": "1000"
      },
      "aggs": {
        "usercount-metric": {
          "cardinality": {
            "field": "userId.keyword"
          }
        }
      }
    }
  },
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "x_st": {
              "gte": "now-4h",
              "lte": "now",
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

查询结果

{
  "took" : 106,
  "timed_out" : false,
  "_shards" : {
    "total" : 1565,
    "successful" : 1565,
    "skipped" : 1520,
    "failed" : 0
  },
  "hits" : {
    "total" : 63956,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "usercount-bucket" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "nameless",
          "doc_count" : 8278,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "liu",
          "doc_count" : 2142,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "li",
          "doc_count" : 1928,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "admin",
          "doc_count" : 44395,
          "usercount-metric" : {
            "value" : 1
          }
        },
        {
          "key" : "111111",
          "doc_count" : 1281,
          "usercount-metric" : {
            "value" : 1
          }
        }
      ]
    },
    "usercount" : {
      "value" : 5.0
    }
  }
}