一、背景介紹
問題一:如何對elasticsearch的檢索結果進行去重統計計數。類似mysql 的 select count(*) from a group by b。
問題二:如何對elasticsearch的檢索結果去重後顯示。類似mysql 的select distint(“name”) from a group by b。
二、分析
問題一:
統計計數需要藉助elasticsearch聚合功能結合cardinality實現。
問題二:
方式一:使用字段聚合+top_hots聚合方式。
方式二:使用collapse摺疊功能。
三、DSL 實例
問題一:
// 統計去重數目
GET user/_search
{
"size":0,
"aggs" : {
"name_count" : {
"cardinality" : {
"field" : "name"
}
}
}
}
問題二:
方式一:top_hits 聚合
GET user/_search
{
"query": {
"match_all": {
}
},
"aggs": {
"type": {
"terms": {
"field": "name",
"size": 10
},
"aggs": {
"title_top": {
"top_hits": {
"_source": {
"includes": [
"name"
]
},
"sort": [
{
"name": {
"order": "desc"
}
}
],
"size": 1
}
}
}
}
},
"size": 0
}
方式二:使用 collapse 摺疊
GET user/_search
{
"query": {
"match_all":{}
},
"collapse": {
"field": "name"
}
}
總結:collapse 摺疊比聚合更加簡潔,性能也更加優異。
四、collapse(摺疊)介紹
1、Field Collapsing(字段摺疊)不能與scroll、rescore以及search after 結合使用。
2、使用collapse 的字段如果是 string類型,則es 中對應 keyword。(The field used for collapsing must be a single valued keyword or numeric field with doc_values activated)
3、查看collapse 結果
(1)GET user/_search
{
"query": {
"match": {
"address": "Place"
}
},
"collapse" : {
"field" : "age"
},
"sort": ["age"],
"from": 10
}
(2)Expand collapse results(對於每個摺疊的結果,可以通過inner_hits展開結果)
// 單個inner_hits
GET user/_search
{
"query": {
"match": {
"address": "Place"
}
},
"collapse" : {
"field" : "age",
"inner_hits": {
"name": "test",
"size": 5,
"sort": [{ "age": "asc" }]
},
"max_concurrent_group_searches": 4
},
"sort": ["age"]
}
// 多個inner_hits
GET user/_search
{
"query": {
"match": {
"address": "Place"
}
},
"collapse" : {
"field" : "age",
"inner_hits":[ {
"name": "age",
"size": 2,
"sort": [{ "age": "asc" }]
},
{
"name":"account_number",
"size": 2,
"sort": [{ "account_number": "asc" }]
}],
"max_concurrent_group_searches": 4
},
"sort": ["age"]
}
// max_concurrent_group_searches:允許每組檢索inner_hits的併發請求數 (默認按照線程池的大小或者數據節點數)