本文翻譯自Elasticsearch官方指南的Sorting and Relevance一章的第一節。
原文地址:http://www.elastic.co/guide/en/elasticsearch/guide/current/_sorting.html
排序
ES默認是通過相關度來對結果進行排序的,最相關的文檔在最前面。在本章里,我們闡述我們所說的相關性以及它是如何計算的,但是我們先講解sort參數及其如何使用。
為了根據相關性進行排序,我們需要把相關性表示為一個值。在Elasticsearch里,在返回的查詢結果中,我們用一個浮點數值_score來表示相關性得分,因此默認的排序是按_score降序。
有時候,不能得到一個有意義的相關性得分。比如,下面的查詢只返回了字段user_id值為1的所有的tweets:
GET /_search { "query" : { "filtered" : { "filter" : { "term" : { "user_id" : 1 } } } } }過濾器與_score無關,並且不含任何條件的match_all查詢對所有的文檔的_score都設置為1。換句話說,所有的文檔被認為是相等的相關性。按字段值排序
在這種情況下,可能按tweets的時間排序是有意義的,最近的tweets在最前面。我們可以使用sort參數做到這一點:
GET /_search { "query" : { "filtered" : { "filter" : { "term" : { "user_id" : 1 }} } }, "sort": { "date": { "order": "desc" }} }在結果中,注意到兩點:"hits" : { "total" : 6, "max_score" : null,
"hits" : [ { "_index" : "us", "_type" : "tweet", "_id" : "14", "_score" : null,
"_source" : { "date": "2014-09-24", ... }, "sort" : [ 1411516800000 ]
}, ... }
_score沒有被計算出來的,因為在排序中不被使用。
date字段的值,被表示為從時間紀元開始的毫秒數,在sort值里返回。
第一,每一個結果中都多了一個新的元素:sort,它包含我們用作排序的那個字段值。在這個例子中,我們按date排序,date是按着從紀元時間的毫秒數加入索引。這段長數字
1411516800000與日期字符串
2014-09-24 00:00:00UTC是等價的。
第二,字段_score與max_score都是null.計算_score很花費時間,況且通常它唯一的目的就是為了排序。我們不是按照相關性排序,所以跟蹤_score是沒有意義的。如果你仍然還想計算_score,你可以將track_scores參數設置為true.
TIP: 作為一個快捷方式,你可以指定要排序的字段名字:
"sort": "number_of_children"字段名默認按升序排序,_score默認按降序排序。多級排序
我們也許要結合_score與date進行查詢,在展示所有匹配結果的時候,首先按照date排序,然后按相關度_score排序。
GET /_search { "query" : { "filtered" : { "query": { "match": { "tweet": "manage text search" }}, "filter" : { "term" : { "user_id" : 2 }} } }, "sort": [ { "date": { "order": "desc" }}, { "_score": { "order": "desc" }} ] }
順序是很重要的。結果首先按第一個標准排序。只有當結果的第一個sort 值相同時,然后再按第二個標准排序,等等。
多級排序不是必須含有_score字段。在腳本里,你可以使用幾個不同的fields,geo-distance或者自定義值排序。
NOTE:Query-string 查詢也支持在查詢字符串里使用sort參數自定義排序:
GET /_search?sort=date:desc&sort=_score&q=search
多值字段排序
當排序字段有不止一個值時,請記住,這些值沒有任何內部順序;一個多值字段只是一袋值(譯者注:所有值可以看做一個整體)。你選擇哪個進行排序呢?對於數字與日期類型,你可以通過min,max,avg或者sum等排序模式,將一個多值字段減少為一個值。例如,你可以通過如下方式,在date字段值集合中的最早的那個日期進行排序:"sort": { "dates": { "order": "asc", "mode": "min" } }