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(文档值)

 

posted @ 2023-01-14 11:06  欢乐豆123  阅读(1601)  评论(0编辑  收藏  举报