es-collapse查询
es-collapse 字段折叠去重查询
前提
我们知道,在mysql有distinct去重查询,那么在es中如何针对字段去重呢?
最近在使用es查询时,有这样的需求,详情如下:
1. 返回数据按照id降序排序,针对用户ID(user_id)对数据进行去重
2. 同一个用户ID如果存在多条记录,保留主键id值最小的那个
1 { 2 "lists": [ 3 { 4 "id": 7840915, 5 "time": 1673512772, 6 "user_id": 23004000, 7 "target_id": 14016237, 8 }, 9 { 10 "id": 7840916, 11 "time": 1673494355, 12 "user_id": 20073846, 13 "target_id": 14016237 14 }, 15 { 16 "id": 7840914, 17 "target_id": 14016237, 18 "user_id": 20073846, 19 "time": 1673493919 20 },
{ 28 "id": 7840845, 29 "target_id": 14016237, 30 "user_id": 23001854, 31 "time": 1673442359 32 } 33 ] 34 }
1. 实现方案分析
这里有两种实现方案:
1)top_hits + 聚合统计agg
查询语句参考:
1 GET example/_search 2 { 3 "query": { 4 "bool": { 5 "must": [ 6 { 7 "term": { 8 "target_id": "14016237" 9 } 10 } 11 ] 12 } 13 }, 14 "_source": [ 15 "id", 16 "title" 17 ], 18 "aggs": { 19 "phone_count": { 20 "terms": { 21 "field": "user_id" 22 } 23 } 24 } 25 }
从查询结果中摘取一部分:
1 { 2 "aggregations": { 3 "phone_count": { 4 "doc_count_error_upper_bound": 0, 5 "sum_other_doc_count": 0, 6 "buckets": [ 7 { 8 "key": 20073846, 9 "doc_count": 2 10 }, 11 { 12 "key": 20036806, 13 "doc_count": 1 14 }, 15 { 16 "key": 23001854, 17 "doc_count": 1 18 }, 19 { 20 "key": 23004000, 21 "doc_count": 1 22 } 23 ] 24 } 25 } 26 }
2)es5以后的新特性collapse(字段折叠)
查询语句参考:
1 GET example/_search 2 { 3 "query": { 4 "bool": { 5 "must": [], 6 "filter": [ 7 { 8 "term": { 9 "target_id": "14016237" 10 } 11 } 12 ] 13 } 14 }, 15 "_source": [ 16 "id", 17 "user_id", 18 "expend_type", 19 "@timestamp" 20 ], 21 "size": "15", 22 "collapse": { 23 "field": "user_id", //按user_id字段进行折叠 24 "inner_hits": { 25 "name": "expend_list", //查看用户信息结果键名 26 "size":1, //每个折合集文档数 27 "sort":[{"id":"asc"}] //每个折合集文档排序规则
"_source": [] //文档的字段 28 } 29 }, 30 "sort":[{"id":"desc"}] 31 }
说明:inner_hits是用于针对折叠字段(这里是user_id重复的数据)筛选排序而指定的规则,其中:name相当于别名,size是返回的折叠集结果数量,sort是针对user_id重复的数据根据指定规则来进行排序
从查询结果中摘取一部分:
1 { 2 "took" : 6, 3 "timed_out" : false, 4 "_shards" : { 5 "total" : 15, 6 "successful" : 15, 7 "skipped" : 0, 8 "failed" : 0 9 }, 10 "hits" : { 11 "total" : { 12 "value" : 6, 13 "relation" : "eq" 14 }, 15 "max_score" : null, 16 "hits" : [ 17 {
... 35 "inner_hits" : { 36 "expend_list" : { 37 "hits" : { 38 "total" : { 39 "value" : 2, 40 "relation" : "eq" 41 }, 42 "max_score" : null, 43 "hits" : [ 44 { 45 "_index" : "example", 46 "_type" : "_doc", 47 "_id" : "7840914", 48 "_score" : null, 49 "_source" : { 50 "target_id" : 14016237, 51 "user_id" : 20073846, 52 "id" : 7840914, 53 "time" : 1673493919 54 }, 55 "sort" : [ 56 7840914 57 ] 58 }, 59 { 60 "_index" : "example", 61 "_type" : "_doc", 62 "_id" : "7840916", 63 "_score" : null, 64 "_source" : { 65 "id" : 7840916, 67
"time" : 1673494355, 68 "user_id" : 20073846, 69 "target_id" : 14016237 70 }, 71 "sort" : [ 72 7840916 73 ] 74 } 75 ] 76 } 77 } 78 } 79 }
... 100 ] 101 } 102 }
2. 性能比较
collapse 允许基于字段对结果进行折叠。折叠操作是通过每个选择每个折叠键的顶部文档(top hits)来实现的
不需要每次都在完整的结果集上对为每个折叠主键计算实际的 doc values 值,只对 top hits 这小部分数据操作就可以,因此和 term agg 相比要节省很多内存
3. 使用collapse注意事项
1)响应结果中的hits总数表示匹配的文档总数而不是折叠的,去重后的聚合总数是未知的。
2)用于折叠的字段必须是单值的keyword或numeric字段并开启doc_values(文档值)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)