Elasticsearch查询整合:合并查询还是使用OR类型运算符?
最优方案:合并为单个嵌套聚合查询
绝对推荐你把两个查询合并成一个,用嵌套聚合来分别统计visible为true和false的情况——这是最优方案,不管从性能还是数据整合的便捷性来说都完胜分开查询或者简单用OR的方式。
为什么不选其他方案?
- 分开两次查询:不仅多一次网络请求,还得手动合并两个时间序列的结果,容易出现时间对齐误差,而且Elasticsearch需要重复扫描相同的数据集,性能浪费。
- 简单用OR:只能拿到符合条件的文档总数,根本没法区分哪部分是加载(
visible=true)哪部分是卸载(visible=false),完全满足不了你要分别统计的需求。
具体实现步骤
我们的思路是:保留共同的查询条件(商户、时间范围),去掉原来单独的visible过滤,然后在日期直方图聚合内部,嵌套一个按visible字段分组的terms聚合,这样就能在同一个小时维度下,同时拿到加载和卸载的次数。
合并后的查询体
{ "size": 0, "query": { "bool": { "must": [ {"match": {"merchant": "a6xzTHtpQs"}}, {"range": {"time": {"gte": "2018-04-02T06:00:00", "lte": "2018-04-03T05:59:59", "time_zone": "+00:00"}}} ] } }, "aggs": { "daily": { "date_histogram": { "field": "time", "interval": "hour", "time_zone": "+00:00", "min_doc_count": 0, "extended_bounds": { "min": "2018-04-02T06:00:00", "max": "2018-04-03T05:59:59" } }, "aggs": { "visible_status": { "terms": { "field": "visible", "size": 2 // 仅两种状态,设置为2足够 } } } } } }
R语言elastic包调用与结果解析
library(elastic) # 构造合并后的查询JSON combined_body <- '{ "size": 0, "query": { "bool": { "must": [ {"match": {"merchant": "a6xzTHtpQs"}}, {"range": {"time": {"gte": "2018-04-02T06:00:00", "lte": "2018-04-03T05:59:59", "time_zone": "+00:00"}}} ] } }, "aggs": { "daily": { "date_histogram": { "field": "time", "interval": "hour", "time_zone": "+00:00", "min_doc_count": 0, "extended_bounds": { "min": "2018-04-02T06:00:00", "max": "2018-04-03T05:59:59" } }, "aggs": { "visible_status": { "terms": { "field": "visible", "size": 2 } } } } } }' # 发送查询(替换成你的索引名) response <- search(body = combined_body, index = "your_index_name") # 解析聚合结果为统一数据集 agg_buckets <- response$aggregations$daily$buckets result_df <- data.frame( hour = as.POSIXct(sapply(agg_buckets, function(x) x$key_as_string), tz = "UTC"), load_count = sapply(agg_buckets, function(x) { # 提取visible=true的计数,无数据则返回0 true_bucket <- Filter(function(b) b$key == "true", x$visible_status$buckets) if (length(true_bucket) > 0) true_bucket[[1]]$doc_count else 0 }), unload_count = sapply(agg_buckets, function(x) { # 提取visible=false的计数,无数据则返回0 false_bucket <- Filter(function(b) b$key == "false", x$visible_status$buckets) if (length(false_bucket) > 0) false_bucket[[1]]$doc_count else 0 }) ) # 查看最终整合后的数据集 print(result_df)
这样你就能直接得到一个包含小时时间、加载次数、卸载次数的完整数据集,一次请求完成所有统计,既高效又避免了数据合并的麻烦。
内容的提问来源于stack exchange,提问作者Mus
相关产品推荐
相关产品推荐

