top_hits指標聚合器用於跟蹤正在聚合的相關文檔。
為了讓每個桶能聚合最佳文檔,該聚合器通常會用作子聚合器(sub aggregator)。
top_hits聚合器能有效地利用桶聚合器,這樣它就能根據特定字段來對結果集進行分組。
一個或多個桶聚合器可確定如何將結果集切分到哪個屬性中.
選項
- from - 要獲取的第一個結果的偏移.
- size - 每個桶返回的最大匹配數。默認只返回前三個匹配.
- sort - 指定匹配的排序方式. 默認會主查詢的評分排序(降序).
每個匹配支持的特性
由於top_hits聚合支持多個命中特性,因此它能返回常規搜索命中:
- Highlighting
- Explain
- Named filters and queries
- Source filtering
- Stored fields
- Script fields
- Doc value fields
- Include versions
示例
在下面的示例中,我們會根據tag來對questions進行分組,對於每個tag,我們只顯示最後激活的問題.對於每個問題,source中只包含title字段(示例中是date和price字段).
POST /sales/_search?size=0
{
"aggs": {
"top_tags": {
"terms": {
"field": "type",
"size": 3
},
"aggs": {
"top_sales_hits": {
"top_hits": {
"sort": [
{
"date": {
"order": "desc"
}
}
],
"_source": {
"includes": [ "date", "price" ]
},
"size" : 1
}
}
}
}
}
}
可能的響應:
{
...
"aggregations": {
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "hat",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "sale",
"_id": "AVnNBmauCQpcRyxw6ChK",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 200
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "t-shirt",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "sale",
"_id": "AVnNBmauCQpcRyxw6ChL",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 175
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "bag",
"doc_count": 1,
"top_sales_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "sale",
"_id": "AVnNBmatCQpcRyxw6ChH",
"_source": {
"date": "2015/01/01 00:00:00",
"price": 150
},
"sort": [
1420070400000
],
"_score": null
}
]
}
}
}
]
}
}
}
字段摺疊示例
字段摺疊或結果分組只是一種功能,它可以將結果集按邏輯分組,每組返回前面幾個文檔.
組的順序由組中第一個文檔的相關性所決定. 在Elasticsearch中,這可以通過將top_hits包裝為桶聚合的子聚合器來實現.
在下面的示例中,我們將搜索已爬取的網頁. 針對每個網頁,我們都存儲了網頁的body和它所屬的domain. 通過在domain字段上定義terms聚合,我們可以將結果集按domain進行分組.
然後,我們還將top_hits 聚合定義為了子聚合,以便每個桶收集最佳匹配。
此外,我們還定義了max 聚合,它會使用terms聚合的order特性來返回桶中相關性最高的文檔.
POST /sales/_search
{
"query": {
"match": {
"body": "elections"
}
},
"aggs": {
"top_sites": {
"terms": {
"field": "domain",
"order": {
"top_hit": "desc"
}
},
"aggs": {
"top_tags_hits": {
"top_hits": {}
},
"top_hit" : {
"max": {
"script": {
"source": "_score"
}
}
}
}
}
}
}
目前,為了能確保terms聚合中的桶能根據每個域中的相關網頁得分進行排序,還需要依靠max (或min)聚合器.不幸的是,top_hits聚合還不能使用terms聚合中的order選項.
top_hits對nested或reverse_nested聚合器的支持
如果將top_hits 聚合包裝在nested或reverse_nested 聚合中,那麼它會嵌套命中.
嵌套命中在某種意義上是隱藏的迷你文檔,它是常規文檔的一部分,在映射中已經配置了嵌套字段類型。如果top_hits聚合器包含在 nested 或reverse_nested聚合中,則它會取消這些隱藏文檔。
有關嵌套的詳細信息,請參考nested類型映射。
如果在單個文檔中配置了nested類型,那麼在索引時,實際上會產生多個Lucene文檔,只不過它們共享了同一id. 為了確定嵌套命中的身份,需要的不僅僅是id,還需要它們的嵌套標識.
嵌套標識保存在搜索命中的_nested字段中,還包括數組字段和嵌套匹配所屬的數組字段的偏移量。 偏移量基於零。
考慮以下映射:
PUT /sales
{
"mappings": {
"product" : {
"properties" : {
"tags" : { "type" : "keyword" },
"comments" : { #1
"type" : "nested",
"properties" : {
"username" : { "type" : "keyword" },
"comment" : { "type" : "text" }
}
}
}
}
}
}
1.comments是一個數組,它是product對象下的一個嵌套文檔.
添加一些文檔:
PUT /sales/product/1?refresh
{
"tags": ["car", "auto"],
"comments": [
{"username": "baddriver007", "comment": "This car could have better brakes"},
{"username": "dr_who", "comment": "Where's the autopilot? Can't find it"},
{"username": "ilovemotorbikes", "comment": "This car has two extra wheels"}
]
}
現在執行以下top_hits 聚合(包裝在nested聚合中):
POST /sales/_search
{
"query": {
"term": { "tags": "car" }
},
"aggs": {
"by_sale": {
"nested" : {
"path" : "comments"
},
"aggs": {
"by_user": {
"terms": {
"field": "comments.username",
"size": 1
},
"aggs": {
"by_nested": {
"top_hits":{}
}
}
}
}
}
}
}
帶有嵌套命中的命中響應片段,它位於數組字段comments的第1個插槽:
{
...
"aggregations": {
"by_sale": {
"by_user": {
"buckets": [
{
"key": "baddriver007",
"doc_count": 1,
"by_nested": {
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_nested": {
"field": "comments", #1
"offset": 0 #2
},
"_score": 0.2876821,
"_source": {
"comment": "This car could have better brakes", #3
"username": "baddriver007"
}
}
]
}
}
}
...
]
}
}
}
}
1 包含嵌套命中的數組字段名稱
2 嵌套命中在包含數組中的位置
3 nested hit的source
如果請求帶有_source,那麼只會返回嵌套對象的source部分,不會返回文檔的整個source.
嵌套對象內部的存儲字段可通過駐包裝在nested或reverse_nested聚合內的top_hits聚合來訪問.
僅在hit中存在_nested字段時才有嵌套命中 ,反之則沒有嵌套命中.
在沒有啟用_source的情況下,可使用_nested的信息來解析原始source.
如果在映射中定義了多個級別的嵌套對象類型,為了表現嵌套命中的層次(兩層或更深),_nested展示的信息也可以是分層的.
在下面的示例中,嵌套命中位於字段nested_grand_child_field的第一個槽中,而它又位於nested_child_field字段的第二個緩衝區中:
...
"hits": {
"total": 2565,
"max_score": 1,
"hits": [
{
"_index": "a",
"_type": "b",
"_id": "1",
"_score": 1,
"_nested" : {
"field" : "nested_child_field",
"offset" : 1,
"_nested" : {
"field" : "nested_grand_child_field",
"offset" : 0
}
}
"_source": ...
},
...
]
}
...
全部指標聚合,請參考
單值指標聚合
多值指標聚合
地理位置相關聚合
可執行Map-Reduce計算的聚合
閱讀更多 Java源 的文章