1. 程式人生 > 其它 >Elasticsearch 去重查詢

Elasticsearch 去重查詢

1、前言

 

最近遇到一個 es 資料查詢去重的需求,我這邊需要的是獲取去重後的結果,查詢官網資料和各位大神的經驗後,總結一下 elasticsearch 去重查詢功能。

 

2、Elasticsearch 去重功能

 

  1. 關係型資料庫中,比如 MySQL,可以通過 distinct 進行去重,一般分為兩種:

 

  • 1 ) 統計去重後的數量

 

select distinct(count(1)) from test;

 

  • 2 ) 獲取去重後的結果

 

select distinct name,sex from person;

 

test,person 為對應的表名。

 

  1. Elasticsearch 類似功能的實現方式

 

  • 1 ) es 查詢結果進行去重計數

    es 的去重計數工卡可以通過 es 的聚合功能 + Cardinality 聚合函式來實現

  • 2 ) es 查詢結果去重後顯示

    去重顯示有兩種方式:

    (1) 使用欄位聚合 + top_hits 聚合方式

    (2) 使用 collapse 摺疊功能 (5.3 後版本提供)

    我這裡使用的 es 是 2.4 的版本,JavaApi 使用的是第一種方式,5.x,6.x 的版本也可以使用

 

3、DSL 原始碼

 

可以通過 es head 外掛來進行查詢測試,user_onoffline_log 是有的索引名字,uid 是其中的一個欄位,uid_aggs 是聚合的名字,可以隨便自定義。

 

1)統計去重數目。

 

POST user_onoffline_log/_search
{
  "query": {
    "match_all": {}
  },
  "size": 0,
  "aggs": {
    "uid_aggs": {
      "cardinality": {
        "field": "uid"
      }
    }
  }
}

 

結果:

 

{
  "took": 565,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 43326369,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "uid_aggs": {
      "value": 12243
    }
  }
}

 

可以看到 uid 欄位去重後的計數值為 12243。

 

2)返回去重內容

 

方式一:top_hits 聚合

 

POST /user_onoffline_log/
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "uid_aggs": {
      "terms": {
        "field": "uid",
        "size": 1
      },
      "aggs": {
        "uid_top": {
          "top_hits": {
            "sort": [
              {
                "uid": {
                  "order": "desc"
                }
              }
            ],
            "size": 1
          }
        }
      }
    }
  },
  "size": 0
}

 

可以通過 size 設定顯示的數量,上面 aggs 的 size 設定的 1,結果:

 

{
    "took":2318,
    "timed_out":false,
    "_shards":{
        "total":200,
        "successful":5,
        "failed":195,
        "failures":[
            {
                "shard":0,
                "index":"stamgr-logstash-2018.03.06",
                "node":"kUbpfLDMRLuAnloYBBRGng",
                "reason":{
                    "type":"search_parse_exception",
                    "reason":"No mapping found for [uid] in order to sort on"
                }
            }
        ]
    },
    "hits":{
        "total":43326369,
        "max_score":0,
        "hits":[

        ]
    },
    "aggregations":{
        "uid_aggs":{
            "doc_count_error_upper_bound":1909,
            "sum_other_doc_count":2174528,
            "buckets":[
                {
                    "key":"",
                    "doc_count":41151839,
                    "uid_top":{
                        "hits":{
                            "total":41151839,
                            "max_score":null,
                            "hits":[
                                {
                                    "_index":"user_onoffline_log",
                                    "_type":"logs",
                                    "_id":"AWYDAu4otdWc46rphdZz",
                                    "_score":null,
                                    "_source":{
                                        "uid":"",
                                        "ip":"",
                                        "mac":"00:5a:39:ec:1c:e4",
                                        "ap_serial_id_online":"219801A0REM173004134",
                                        "ap_mac_online":"9c:06:1b:a8:18:e0",
                                        "ap_name_online":"lFkFq_xiangyundao_sihailujiaokou_W-E_AP02",
                                        "location_online":"祥雲道與四海路交口由西向東第2點",
                                        "zone_online":"祥雲道",
                                        "ap_serial_id_offline":"219801A0REM173004692",
                                        "ap_mac_offline":"9c:06:1b:a8:00:00",
                                        "ap_name_offline":"lFkFq_xiangyundao_sihailujiaokou_W-E_AP03",
                                        "location_offline":"祥雲道與四海路交口由西向東第3點",
                                        "zone_offline":"祥雲道",
                                        "area":"開發區",
                                        "area_id":"001",
                                        "province":"",
                                        "city":"",
                                        "corp":"",
                                        "type":"3",
                                        "online_time":"201809222310",
                                        "offline_time":"201809230440",
                                        "duration":330
                                    },
                                    "sort":[
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
}

 

方式二:摺疊

 

POST /user_onoffline_log/
{
    "query":{
        "match_all":{

        }
    },
    "collapse":{
        "field":"uid"
    }
}

 

方式二較方式一:

 

  • 簡化;
  • 效能好很多。