如何用ElasticSearch实现移动端APP版本使用量统计及可视化?
移动端APP版本统计:ElasticSearch查询与可视化方案
我来帮你解决这个统计每个客户端最新版本并聚合计数的问题,结合你不想用update/upsert、只添加文档的需求,下面分两部分给出具体方案:
问题背景
你需要在ElasticSearch中存储移动端APP的初始化事件数据,统计每个客户端的最新版本并按版本分组计数(即安装量),现有数据示例如下:
- clientId: ABC, clientVersion: 1.2.3, time: 2018-01-01
- clientId: DEF, clientVersion: 1.2.3, time: 2018-01-02
- clientId: GHI, clientVersion: 1.2.3, time: 2018-01-03
- clientId: DEF, clientVersion: 1.2.3, time: 2018-01-04
- clientId: GHI, clientVersion: 1.2.4, time: 2018-01-05
期望得到的统计结果是:
- version 1.2.3: 2个安装量(ABC、DEF)
- version 1.2.4: 1个安装量(GHI)
你尝试过用top_hits聚合按clientId去重,但发现无法在top_hits下添加子聚合来进一步统计版本,接下来看具体解决方案。
1. ElasticSearch 查询实现
我们可以用**scripted_metric聚合**来实现和你内存处理完全一致的逻辑:先跟踪每个客户端的最新版本,再按版本统计数量。这个聚合不需要依赖嵌套子聚合的限制,直接在分片和节点层面处理数据。
具体查询语句如下:
GET /metric/_search { "size": 0, // 不需要返回原始文档,只看聚合结果 "aggs": { "latest_version_installs": { "scripted_metric": { "init_script": "state.client_latest = [:]", // 初始化存储每个客户端的最新版本和时间 "map_script": """ def client_id = doc['clientId'].value; def current_time = doc['time'].value; def current_version = doc['clientVersion'].value; // 如果客户端不存在,或者当前文档时间更新,就更新最新版本 if (!state.client_latest.containsKey(client_id) || current_time.isAfter(state.client_latest[client_id].time)) { state.client_latest[client_id] = ['time': current_time, 'version': current_version]; } """, "combine_script": """ // 分片内统计各版本的客户端数量 def version_counts = [:]; state.client_latest.values().each { entry -> def version = entry.version; version_counts[version] = (version_counts[version] ?: 0) + 1; } return version_counts; """, "reduce_script": """ // 汇总所有分片的统计结果 def final_counts = [:]; states.each { shard_result -> shard_result.each { version, count -> final_counts[version] = (final_counts[version] ?: 0) + count; } } return final_counts; """ } } } }
执行这个查询后,你会在aggregations.latest_version_installs.value中得到期望的版本-安装量统计结果。
2. Kibana/Grafana 可视化实现
如果觉得写复杂的聚合脚本太麻烦,也可以直接在可视化工具中配置实现:
Kibana 实现步骤
- 创建数据视图:确保你的
metric索引已经创建了包含clientId、clientVersion、time字段的数据视图。 - 创建过滤后的保存搜索:
- 进入Discover页面,添加一个脚本过滤器:
这个过滤器会只保留每个客户端的最新时间对应的文档。doc['time'].value == (max(time) over (partition by clientId)) - 保存这个搜索,命名为「最新客户端版本」。
- 进入Discover页面,添加一个脚本过滤器:
- 创建可视化图表:
- 选择「条形图」或「饼图」类型,数据源选择刚才保存的「最新客户端版本」。
- 在Metrics面板,选择「Unique Count」,字段选
clientId(统计唯一客户端数)。 - 在Buckets面板,添加「Terms」聚合,字段选
clientVersion,按版本分组。 - 调整图表样式,就能得到各版本的安装量可视化。
Grafana 实现步骤
- 配置ES数据源:确保已经连接到你的ElasticSearch集群,索引选择
metric。 - 创建面板:
- 选择「条形图」或「饼图」面板,进入Query配置:
- Metric选择「Count」,然后添加两个Group by:
- 第一个Group by选「Terms」,字段
clientVersion,用于按版本分组。 - 第二个Group by选「Filter」,添加脚本筛选:
doc['time'].value == (max(time) over (partition by clientId))
- 第一个Group by选「Terms」,字段
- Metric选择「Count」,然后添加两个Group by:
- 进入Transform配置,添加「Reduce」变换,选择「Unique Count」,字段选
clientId,这样就会统计每个版本下的唯一客户端数。 - 调整图表的显示设置,完成可视化配置。
- 选择「条形图」或「饼图」面板,进入Query配置:
内容的提问来源于stack exchange,提问作者Ali Ok
相关产品推荐
相关产品推荐

