ElasticSearch 2 (33) - 信息聚合系列之聚合過濾
摘要
聚合范圍限定還有一個自然的擴展就是過濾。因為聚合是在查詢結果范圍內操作的,任何可以適用於查詢的過濾器也可以應用在聚合上。
版本
elasticsearch版本: elasticsearch-2.x
內容
聚合范圍限定還有一個自然的擴展就是過濾。因為聚合是在查詢結果范圍內操作的,任何可以適用於查詢的過濾器也可以應用在聚合上。
Filtered
查詢(Filtered Query)
如果我們想找到售價在 $10,000 美元之上的所有汽車同時也為這些車計算平均售價,可以簡單地使用一個 filtered
查詢:
GET /cars/transactions/_search
{
"size" : 0,
"query" : {
"filtered": {
"filter": {
"range": {
"price": {
"gte": 10000
}
}
}
}
},
"aggs" : {
"single_avg_price": {
"avg" : { "field" : "price" }
}
}
}
這正如我們在前面章節中討論過那樣,從根本上講,使用 filtered
查詢和使用 match
查詢沒有任何區別。查詢(包括了一個過濾器)返回一組文檔的子集,聚合正是操作這些文檔。
過濾桶(Filter Bucket)
但是如果我們只想對聚合結果過濾怎么辦?假設我們正在創建一個可以搜索汽車經銷商的頁面,我們希望顯示用戶搜索的結果,但是我們同時也想在頁面上提供更豐富的信息,包括(與搜索匹配的)上個月度汽車的平均售價
這里我們無法簡單的做范圍限定,因為有兩個不同的條件。搜索結果必須是 ford
,但是聚合結果必須滿足 ford
AND sold > now - 1M
。
為了解決這個問題,我們可以用一種特殊的桶,叫做過濾桶。我們可以指定一個過濾桶,當文檔滿足過濾桶的條件時,我們將其加入到桶內。
查詢結果如下:
GET /cars/transactions/_search
{
"size" : 0,
"query":{
"match": {
"make": "ford"
}
},
"aggs":{
"recent_sales": {
"filter": { #1
"range": {
"sold": {
"from": "now-1M"
}
}
},
"aggs": {
"average_price":{
"avg": {
"field": "price" #2
}
}
}
}
}
}
#1 使用過濾桶在查詢范圍基礎上應用過濾器。
#2 avg
度量只會對 ford
和 一月以內售出 的文檔計算平均售價。
因為 filter
桶和其他桶的操作方式一樣,所以可以隨意將其他桶和度量嵌入其中。所有嵌套的組件都會 “繼承” 這個過濾,這使我們可以按需針對聚合過濾出選擇部分。
展示過濾器(Post Filter)
目前為止,我們可以同時對搜索結果和聚合結果進行過濾(一個 filtered
查詢),以及針對聚合結果的一部分進行過濾(filter
桶)
我們可能會想,“有只對搜索結果進行過濾而不過濾聚合結果的方式嗎?”答案是使用 post_filter
。
它是頂層搜索請求元素接收一個過濾器。這個過濾器在查詢之后執行(這正是該過濾器的名字的由來:它在查詢之后(post
)執行)。正因為它在查詢之后執行,它對查詢范圍沒有任何影響,所以對聚合也不會有任何影響。
我們可以利用這個行為對查詢條件應用更多的過濾器,而不會影響其他的操作,就如 UI 上的各個分類面。讓我們為汽車經銷商設計另外一個搜索頁面,這個頁面允許用戶搜索汽車同時可以根據顏色來過濾。顏色的選項是通過聚合獲得的:
GET /cars/transactions/_search
{
"size" : 0,
"query": {
"match": {
"make": "ford"
}
},
"post_filter": { #1
"term" : {
"color" : "green"
}
},
"aggs" : {
"all_colors": {
"terms" : { "field" : "color" }
}
}
}
#1 post_filter
元素是頂層元素而且僅對命中結果進行過濾。
查詢部分找到所有的 ford
汽車,然后用 terms
聚合創建一個顏色列表。因為聚合對查詢范圍進行操作,顏色列表與福特汽車有的顏色相對應。
最后,post_filter
會過濾搜索結果,只展示綠色福特汽車。這在查詢執行過后發生,所以聚合不受影響。
這通常對 UI 的連貫一致性很重要,可以想象用戶在界面商選擇了一類顏色(比如:green
綠色),期望的是搜索結果已經被過濾了,而不是過濾界面上的選項。如果我們應用 filtered
查詢,界面會馬上變成只顯示 green
作為選項,這不是用戶想要的!
警告
性能考慮(Performance consideration)
只在我們需要區別過濾搜索結果和聚合結果時使用
post_filter
,有時用戶會在普通搜索使用post_filter
。不要這么做!
post_filter
的特性是在查詢之后執行,所以任何過濾所帶來的好處(比如緩存)都會完全失去。
post_filter
應該只在我們需要不同過濾時,只與聚合一起使用。
小結(Recap)
選擇合適類型的過濾(如:搜索命中、聚合或兩者兼有)通常和我們期望如何表現用戶交互有關。選擇合適的過濾器(或組合)取決於我們期望如何將結果呈現給用戶。
filtered
查詢同時影響搜索結果和聚合結果。filter
桶影響聚合。post_filter
只影響搜索結果。