Elasticsearch:对搜索结果排序 - Sort
我們知道在默認的情況下,搜索的結果是按照相關性來進行排序的。分數最高的排在前面,而分數低的向后依次排序。在絕大多數的情況下,這種排序是非常有效的,而且也適用我們的很多用例。即便針對分數,我們也可以對搜索的結果進行定制。關于這個分數是如何及算出來的,你可以參考我之前的文章 “Elasticsearch:使用 Elasticsearch 提高網站搜索查詢的相關性”。我們也可以使用一下方法來定制我們的分數。你可以閱讀如下的文章:
-
Elasticsearch:使用 function_score 及 script_score 定制搜索結果的分數
-
Elasticsearch:定制分詞器(analyzer)及相關性
然而,有時,我們并不想按照默認的分數進行排序。比如我們想按照姓氏的順序來排序,或者按照價格的高低來排序,或者按照距離的遠近來進行排序。Elasticsearch 允許你使用 sort 來使你在特定字段上添加一種或多種排序。 每種排序也可以顛倒。 排序是在每個字段級別上定義的,_score 的特殊字段名稱按分數排序,_doc 按索引順序排序。
在今天的文章中,我來詳述如何使用 sort 來進行排序。
準備數據
我們先在 Kibana 中使用如下的命令來創建一個叫做 mybooks 的索引:
PUT mybooks {"mappings": {"properties": {"date": {"type": "date"},"description": {"type": "text"},"offer": {"type": "nested","properties": {"name": {"type": "keyword"},"price": {"type": "long"}}},"position": {"type": "long"},"price": {"type": "long"},"publisher": {"type": "keyword"},"quantity": {"type": "long"},"title": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"uuid": {"type": "keyword"},"location": {"type": "geo_point"}}} }在上面的索引中,我有意識地設置了整型類,date,geo_point,text,keyword 及 nested 各個類型的數據。接著我們使用如下的命令來寫入數據到索引中:
POST _bulk/ {"index":{"_index":"mybooks", "_id":"1"}} {"uuid":"11111","position":1, "title":"Joe Bates", "description":"Joe Testere nice guy", "date":"2015-10-22","price":[1, 2, 3], "quantity":50, "publisher": "RELX", "offer": [{"name":"book1", "price": 5}], "location":{"lat":"39.718256","lon":"116.367910"}} {"index":{"_index":"mybooks", "_id":"2"}} {"uuid":"22222","position":2, "title":"Joe Tester","description":"Joe Testere nice guy", "date":"2015-10-22", "price":[4, 5, 6], "quantity":50, "publisher": "RELX", "offer": [{"name":"book2", "price": 5}], "location":{"lat":"39.718256","lon":"116.367910"}} {"index":{"_index":"mybooks", "_id":"3"}} {"uuid":"33333", "position":3, "title":"Bill Baloney","description":"Bill Testere nice guy","date":"2016-06-12","price":[7, 8, 9], "quantity":34, "publisher": "Thomson Reuters", "offer": [{"name":"book3", "price": 10}], "location":{"lat":"40.718256","lon":"117.367910"}} {"index":{"_index":"mybooks", "_id":"4"}} {"uuid":"44444", "position":4, "title":"Bill Klingon","description":"Bill is not a nice guy", "date":"2017-09-21","price":[1, 5, 8], "quantity":33, "offer": [{"name":"book4", "price": 20}],"location":{"lat":"41.718256", "lon":"118.367910"}}在上面,我們使用了4個文檔數據。數據不必太多,只要能說明問題即可。其中第一個文檔和第二個文檔的日期是一樣的。
使用日期來進行排序
我們對搜索的結果按照日期進行排序:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"date": {"order": "desc"}}],"_source": false,"fields": ["date"] }在上面,我們把搜索的結果按照 date 進行降序排序。我們可以看到如下的結果:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "4","_score" : null,"fields" : {"date" : ["2017-09-21T00:00:00.000Z"]},"sort" : [1505952000000]},{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"date" : ["2016-06-12T00:00:00.000Z"]},"sort" : [1465689600000]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"date" : ["2015-10-22T00:00:00.000Z"]},"sort" : [1445472000000]},{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"date" : ["2015-10-22T00:00:00.000Z"]},"sort" : [1445472000000]}]} }首先,我們可以看到 _score 的值為 null。當我一旦使用 sort 時,那么原來的 _score 就沒有任何的意義了。上面的結果顯示它是按照 date 的降序進行返回的。在很多的時候,我們甚至可以對多個字段來進行排序,比如:
GET mybooks/_search?filter_path=**.hits {"query": {"match": {"title": "joe"}},"sort": [{"date": {"order": "desc"}},{"title.keyword": {"order": "desc"}}],"_source": false,"fields": ["date","title"] }在上面,我們搜索 title 里含有 joe 的文檔,并按照 date 降序排列。如果兩個 date 的時間是一致的,那么再按照 title.keyword 來進行降序排序。請注意我們必須使用 title.keyword 而不是 title,這是因為我們不可以針對 text 字段來進行排序的。上面命令的結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"date" : ["2015-10-22T00:00:00.000Z"],"title" : ["Joe Tester"]},"sort" : [1445472000000,"Joe Tester"]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"date" : ["2015-10-22T00:00:00.000Z"],"title" : ["Joe Bates"]},"sort" : [1445472000000,"Joe Bates"]}]} }如果我們把 title.keyword 按照升序排序的話,就是這樣的命令:
GET mybooks/_search?filter_path=**.hits {"query": {"match": {"title": "joe"}},"sort": [{"date": {"order": "desc"}},{"title.keyword": {"order": "asc"}}],"_source": false,"fields": ["date","title"] }注意:_doc 除了是最有效的排序順序之外沒有真正的用例。 因此,如果你不關心文檔返回的順序,那么你應該按 _doc 排序。 這在 scrolling 時特別有用。
Sort mode 選項
Elasticsearch 支持按數組或多值字段排序。 mode 選項控制選擇哪個數組值來對其所屬的文檔進行排序。 mode 選項可以具有以下值:
| min | 選擇最低值。 |
| max | 選擇最高值。 |
| sum | 使用所有值的總和作為排序值。 僅適用于基于數字的數組字段。 |
| avg | 使用所有值的平均值作為排序值。 僅適用于基于數字的數組字段。 |
| median | 使用所有值的中位數作為排序值。 僅適用于基于數字的數組字段。 |
升序排序中的默認排序模式是 min — ?選取最小值。 默認的降序排序模式是max — 取最高值。
針對我們的例子,我們有一個字段 price。它是一個多值的字段。我們現在來對它進行排序,比如:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"price": {"order": "desc","mode": "avg"}}],"_source": false,"fields": ["price"] }在上面,我們針對 price 進行平均值排序:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"price" : [7,8,9]},"sort" : [8]},{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"price" : [4,5,6]},"sort" : [5]},{"_index" : "mybooks","_id" : "4","_score" : null,"fields" : {"price" : [1,5,8]},"sort" : [5]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"price" : [1,2,3]},"sort" : [2]}]} }如上所示,我們在 sort 字段里,我們可以看到 price 的平均值。搜索的結果是按照平均值降序進行排列的。
對數字字段進行排序
對于數字字段,也可以使用 numeric_type 選項將值從一種類型轉換為另一種類型。 此選項接受以下值:["double", "long", "date", "date_nanos"] 并可用于跨多個數據流或索引的搜索,其中排序字段映射不同。
例如考慮這兩個索引:
PUT /index_double {"mappings": {"properties": {"field": { "type": "double" }}} }PUT /index_long {"mappings": {"properties": {"field": { "type": "long" }}} }由于 field 在第一個索引中被映射為雙精度(double),在第二個索引中被映射為長型數(long),因此默認情況下無法使用此字段對查詢兩個索引的請求進行排序。 但是,你可以使用 numeric_type 選項將類型強制為一種或另一種,以便為所有索引強制使用特定類型:
POST /index_long,index_double/_search {"sort" : [{"field" : {"numeric_type" : "double"}}] }在上面的示例中,index_long 索引的值被強制轉換為雙精度,以便與 index_double 索引生成的值兼容。 也可以將浮點字段轉換為 long 但請注意,在這種情況下,浮點被替換為小于或等于參數的最大值(如果值為負,則大于或等于)并且等于 為一個數學整數。
此選項還可用于將使用毫秒分辨率的日期字段轉換為具有納秒分辨率的 date_nanos 字段。 例如考慮這兩個索引:
PUT /index_double {"mappings": {"properties": {"field": { "type": "date" }}} }PUT /index_long {"mappings": {"properties": {"field": { "type": "date_nanos" }}} }這些索引中的值以不同的分辨率存儲,因此對這些字段進行排序將始終將 date 排序在 date_nanos 之前(升序)。 使用 numeric_type 類型選項,可以為排序設置單個分辨率,設置為 date 會將 date_nanos 轉換為毫秒分辨率,而 date_nanos 會將 date 字段中的值轉換為納秒分辨率:
POST /index_long,index_double/_search {"sort" : [{"field" : {"numeric_type" : "date_nanos"}}] }警告:為避免溢出,轉換為 date_nanos 不能應用于 1970 年之前和 2262 年之后的日期,因為納秒表示為 long。
在嵌套對象中排序
Elasticsearch 還支持按一個或多個嵌套(nested)對象內的字段進行排序。 嵌套字段支持的排序具有 nested 排序選項,具有以下屬性:
| path | 定義要排序的嵌套對象。 實際的排序字段必須是此嵌套對象內的直接字段。 按嵌套字段排序時,此字段為必填項。 |
| filter | 嵌套路徑內的內部對象應匹配的過濾器,以便通過排序考慮其字段值。 常見的情況是在嵌套過濾器或查詢中重復查詢/過濾器。 默認情況下,沒有 filter 處于活動狀態。 |
| max_children | 選擇排序值時要考慮的每個根文檔的最大子項數。 默認為無限制。 |
| nested | 與頂級嵌套相同,但適用于當前嵌套對象中的另一個嵌套路徑。 |
注意:如果在沒有嵌套上下文的排序中定義了嵌套字段,Elasticsearch 將拋出錯誤。
嵌套排序示例
在下面的示例中,offer 是一個 nested 類型的字段。 需要指定嵌套 path; 否則,Elasticsearch 不知道需要捕獲哪些嵌套級別的排序值。
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"offer.price": {"mode": "avg","order": "desc","nested": {"path": "offer","filter": {"term": {"offer.name": "book3"}}}}}] }在上面,我們是以 offer.price 來進行降序排列。我們針對 offer.name 為 book3?得到排序的優先級。上面的排序結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "3","_score" : null,"_source" : {"uuid" : "33333","position" : 3,"title" : "Bill Baloney","description" : "Bill Testere nice guy","date" : "2016-06-12","price" : [7,8,9],"quantity" : 34,"publisher" : "Thomson Reuters","offer" : [{"name" : "book3","price" : 10}],"location" : {"lat" : "40.718256","lon" : "117.367910"}},"sort" : [10]},{"_index" : "mybooks","_id" : "1","_score" : null,"_source" : {"uuid" : "11111","position" : 1,"title" : "Joe Bates","description" : "Joe Testere nice guy","date" : "2015-10-22","price" : [1,2,3],"quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book1","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [-9223372036854775808]},{"_index" : "mybooks","_id" : "2","_score" : null,"_source" : {"uuid" : "22222","position" : 2,"title" : "Joe Tester","description" : "Joe Testere nice guy","date" : "2015-10-22","price" : [4,5,6],"quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book2","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [-9223372036854775808]},{"_index" : "mybooks","_id" : "4","_score" : null,"_source" : {"uuid" : "44444","position" : 4,"title" : "Bill Klingon","description" : "Bill is not a nice guy","date" : "2017-09-21","price" : [1,5,8],"quantity" : 33,"offer" : [{"name" : "book4","price" : 20}],"location" : {"lat" : "41.718256","lon" : "118.367910"}},"sort" : [-9223372036854775808]}]} }從上面的結果可以看出來,offer.name 為 book3 的文檔排名最高。
在下面的示例中,parent 字段和 child 字段屬于 nested 類型。 每一層都需要指定 nested.path; 否則,Elasticsearch 不知道需要捕獲哪些嵌套級別的排序值。
POST /_search {"query": {"nested": {"path": "parent","query": {"bool": {"must": {"range": {"parent.age": {"gte": 21}}},"filter": {"nested": {"path": "parent.child","query": {"match": {"parent.child.name": "matt"}}}}}}}},"sort" : [{"parent.child.age" : {"mode" : "min","order" : "asc","nested": {"path": "parent","filter": {"range": {"parent.age": {"gte": 21}}},"nested": {"path": "parent.child","filter": {"match": {"parent.child.name": "matt"}}}}}}] }在按腳本排序和按地理距離排序時也支持嵌套排序。
缺失值
missing 參數指定應如何處理缺少排序字段的文檔:缺失值可以設置為 _last、_first 或自定義值(將用于缺少文檔作為排序值)。 默認值為 _last。
例如:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"publisher": {"order": "desc","missing": "_first"}}],"_source": false,"fields": ["publisher"] }在上,我們在 sort 時,定義如果缺失 publisher 這個字段,那么就排到前面去。上面的搜索結果是:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "4","_score" : null,"sort" : [null]},{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"publisher" : ["Thomson Reuters"]},"sort" : ["Thomson Reuters"]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"publisher" : ["RELX"]},"sort" : ["RELX"]},{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"publisher" : ["RELX"]},"sort" : ["RELX"]}]} }我們可以看到 _id 為 4 的文檔排在第一位,而其它含有 publisher 的文檔是按照降序進行排列的。
注意:如果嵌套的內部對象與nested.filter 不匹配,則使用缺失值。
忽略未映射的字段
默認情況下,如果沒有與字段關聯的映射,則搜索請求將失敗。 unmapped_type 選項允許你忽略沒有映射的字段并且不按它們排序。 此參數的值用于確定要發出的排序值。 這是如何使用它的示例。我們來創建一個如下另外一個索引:
PUT mybooks1 {"mappings": {"properties": {"date": {"type": "date"},"description": {"type": "text"},"offer": {"type": "nested","properties": {"name": {"type": "keyword"},"price": {"type": "long"}}},"position": {"type": "long"},"publisher": {"type": "keyword"},"quantity": {"type": "long"},"title": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"uuid": {"type": "keyword"},"location": {"type": "geo_point"}}} }在上面,我們創建了一個叫做 mybooks1 的索引。請注意它和之前的 mybooks 索引的區別就是它沒有了之前的 price 字段。其它的字段都一樣。我們使用如下命令來創建一個文檔:
POST _bulk/ {"index":{"_index":"mybooks", "_id":"1"}} {"uuid":"99999","position":1, "title":"Joe Bates", "description":"Joe Testere nice guy", "date":"2015-10-22", "quantity":50, "publisher": "RELX", "offer": [{"name":"book1", "price": 5}], "location":{"lat":"39.718256","lon":"116.367910"}}我們使用如下的搜索:
GET mybooks*/_search?filter_path=**.hits {"query": {"match": {"title": "joe"}}, "sort": [{"price": {"order": "desc","mode": "avg"}}] }上面的命令返回的結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "2","_score" : null,"_source" : {"uuid" : "22222","position" : 2,"title" : "Joe Tester","description" : "Joe Testere nice guy","date" : "2015-10-22","price" : [4,5,6],"quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book2","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [5]},{"_index" : "mybooks","_id" : "1","_score" : null,"_source" : {"uuid" : "99999","position" : 1,"title" : "Joe Bates","description" : "Joe Testere nice guy","date" : "2015-10-22","quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book1","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [-9223372036854775808]}]} }如果查詢的任何索引沒有價格映射,則 Elasticsearch 將處理它,就好像存在 long 類型的映射一樣,該索引中的所有文檔都沒有該字段的值。
地理距離排序
允許按 _geo_distance 排序。 這是一個示例,在我們的 mybooks 索引中 location 是一個 geo_point 的類型。我們可以做如下的查詢:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": {"lat": 39.718256,"lon": 116.367910}, "order": "asc","unit": "km","mode": "min","distance_type": "arc","ignore_unmapped": true}}],"_source": false,"fields": ["location"] }在上面,我們以經緯度地點 [116.367910, 39.718256] 為中心,其它文檔距離這個地點按照升序進行排列。上面命令搜索的結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"location" : [{"coordinates" : [116.36791,39.718256],"type" : "Point"}]},"sort" : [0.0]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"location" : [{"coordinates" : [116.36791,39.718256],"type" : "Point"}]},"sort" : [0.0]},{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"location" : [{"coordinates" : [117.36791,40.718256],"type" : "Point"}]},"sort" : [139.9034456345085]},{"_index" : "mybooks","_id" : "4","_score" : null,"fields" : {"location" : [{"coordinates" : [118.36791,41.718256],"type" : "Point"}]},"sort" : [279.0300719062577]}]} }我們可以看到有兩個文檔的距離是 0,而另外的兩個文檔的距離是?139.9034456345085 及?279.0300719062577 公里。
上面的參數描述如下:
| distance_type | 如何計算距離。 可以是圓弧(默認),也可以是平面(速度更快,但在長距離和靠近極點時不準確)。 |
| mode | 如果一個字段有多個地理點,該怎么辦。 默認情況下,升序排序時考慮最短距離,降序排序時考慮最長距離。 支持的值為最小值、最大值、中值和平均值。 |
| unit | 計算排序值時使用的單位。 默認值為 m(米)。 |
| ignore_unmapped | 指示是否應將未映射的字段視為缺失值。 將其設置為 true 等效于在字段排序中指定 unmapped_type。 默認值為 false(未映射的字段會導致搜索失敗)。 |
注意:地理距離排序不支持可配置的缺失值:當文檔沒有用于距離計算的字段的值時,距離將始終被視為等于 Infinity。
上面的搜索也支持如下的格式的坐標表示:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": [116.36791,39.718256],"order": "asc","unit": "km","mode": "min","distance_type": "arc","ignore_unmapped": true}}],"_source": false,"fields": ["location"] }更多關于地理位置坐標的描述,可以閱讀另外一篇文章 “Elasticsearch:理解 Elastic Maps 中的 geohash 及其聚合”。
我們也可以使用 WKT 字符串:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": "POINT(116.36791 39.718256)","order": "asc","unit": "km","mode": "min","distance_type": "arc","ignore_unmapped": true}}],"_source": false,"fields": ["location"] }我們甚至可以使用 Geohash 代碼。請參考我之前的文章??“Elasticsearch:理解 Elastic Maps 中的 geohash 及其聚合”。在該文章中,找那個把經緯度轉為 geohash 的網站。經過轉換 (116.36791 39.718256) 可以轉換為 wx4cbn2x8gd:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": "wx4cbn2x8gd","order": "asc","unit": "km","mode": "min","distance_type": "arc","ignore_unmapped": true}}],"_source": false,"fields": ["location"] }?顯然這個取決于 geohash 的精度。在上面的搜索中,在前兩個的搜索結果中,sort 里的值不再是 0 了。說明它還是有一點誤差的:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"location" : [{"coordinates" : [116.36791,39.718256],"type" : "Point"}]},"sort" : [7.30239509326306E-5]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"location" : [{"coordinates" : [116.36791,39.718256],"type" : "Point"}]},"sort" : [7.30239509326306E-5]},多個參考點
多個地理點可以作為包含任何 geo_point 格式的數組傳遞,例如
GET /_search {"sort": [{"_geo_distance": {"pin.location": [ [ -70, 40 ], [ -71, 42 ] ],"order": "asc","unit": "km"}}],"query": {"term": { "user": "kimchy" }} }文檔的最終距離將是文檔中包含的所有點到排序請求中給定的所有點的最小/最大/平均(通過模式定義)距離。
基于腳本的排序
允許根據自定義腳本進行排序,這是一個示例。
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_script": {"type": "number","order": "desc","script": {"lang": "painless","source": """doc['quantity'].value * params.factor""","params": {"factor": 2}}}}],"_source": false,"fields": ["quantity"] }在上面,我們想知道 quantity 乘以 2 的結果來進行排序:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"quantity" : [50]},"sort" : [100.0]},{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"quantity" : [50]},"sort" : [100.0]},{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"quantity" : [34]},"sort" : [68.0]},{"_index" : "mybooks","_id" : "4","_score" : null,"fields" : {"quantity" : [33]},"sort" : [66.0]}]} }我們可以使用如下的查詢來查看到底哪本書壓貨的錢最多。在下面,我們取沒本書的平均價格:
GET mybooks/_search?filter_path=**.hits {"query": {"match_all": {}},"sort": [{"_script": {"type": "number","order": "desc","script": {"lang": "painless","source": """double total = 0.0;for (int i = 0; i < doc['price'].length; ++i) {total += (double)doc['price'][i];}total = total/3;return total*doc['quantity'].value"""}}}],"_source": false,"fields": ["quantity"] }上面的查詢返回的結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "3","_score" : null,"fields" : {"quantity" : [34]},"sort" : [272.0]},{"_index" : "mybooks","_id" : "2","_score" : null,"fields" : {"quantity" : [50]},"sort" : [250.0]},{"_index" : "mybooks","_id" : "4","_score" : null,"fields" : {"quantity" : [33]},"sort" : [154.0]},{"_index" : "mybooks","_id" : "1","_score" : null,"fields" : {"quantity" : [50]},"sort" : [100.0]}]} }從上面,我們可以看出來 _id 為 3 的書壓貨的錢是最多的。
跟蹤分數
對字段進行排序時,不計算分數。 通過將 track_scores 設置為 true,仍然會計算和跟蹤分數。
GET mybooks/_search?filter_path=**.hits {"track_scores": true,"query": {"match": {"title": "joe"}},"sort": [{"date": {"order": "desc"},"title.keyword": {"order": "desc"},"quantity": {"order": "desc"}}] }上面的命令返回的結果為:
{"hits" : {"hits" : [{"_index" : "mybooks","_id" : "2","_score" : 0.6931471,"_source" : {"uuid" : "22222","position" : 2,"title" : "Joe Tester","description" : "Joe Testere nice guy","date" : "2015-10-22","price" : [4,5,6],"quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book2","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [1445472000000,"Joe Tester",50]},{"_index" : "mybooks","_id" : "1","_score" : 0.6931471,"_source" : {"uuid" : "11111","position" : 1,"title" : "Joe Bates","description" : "Joe Testere nice guy","date" : "2015-10-22","price" : [1,2,3],"quantity" : 50,"publisher" : "RELX","offer" : [{"name" : "book1","price" : 5}],"location" : {"lat" : "39.718256","lon" : "116.367910"}},"sort" : [1445472000000,"Joe Bates",50]}]} }內存考慮
排序時,相關的排序字段值被加載到內存中。 這意味著每個分片應該有足夠的內存來容納它們。 對于基于字符串的類型,排序的字段不應被分析/標記化。 對于數字類型,如果可能,建議將類型顯式設置為更窄的類型(如 short、integer 和 float)。
總結
以上是生活随笔為你收集整理的Elasticsearch:对搜索结果排序 - Sort的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android按钮灰色,Android
- 下一篇: Python爬虫练习(一):酷狗飙升榜前