排序
為了按照相關(guān)性來排序,需要將相關(guān)性表示為一個(gè)數(shù)值。在 Elasticsearch 中, 相關(guān)性得分 由一個(gè)浮點(diǎn)數(shù)進(jìn)行表示,并在搜索結(jié)果中通過 _score 參數(shù)返回, 默認(rèn)排序是 _score 降序。
有時(shí),相關(guān)性評(píng)分對(duì)你來說并沒有意義。例如,下面的查詢返回所有 user_id 字段包含 1 的結(jié)果:
GET /_search
{
"query" : {
"bool" : {
"filter" : {
"term" : {
"user_id" : 1
}
}
}
}
}
這里沒有一個(gè)有意義的分?jǐn)?shù):因?yàn)槲覀兪褂玫氖?filter (過濾),這表明我們只希望獲取匹配 user_id: 1 的文檔,并沒有試圖確定這些文檔的相關(guān)性。 實(shí)際上文檔將按照隨機(jī)順序返回,并且每個(gè)文檔都會(huì)評(píng)為零分。
- 按照字段的值排序
在這個(gè)案例中,通過時(shí)間來對(duì) tweets 進(jìn)行排序是有意義的,最新的 tweets 排在最前。 我們可以使用 sort 參數(shù)進(jìn)行實(shí)現(xiàn):
GET /_search
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }}
}
你會(huì)注意到結(jié)果中的兩個(gè)不同點(diǎn):
"hits" : {
"total" : 6,
"max_score" : null,
"hits" : [ {
"_index" : "us",
"_type" : "tweet",
"_id" : "14",
"_score" : null,
"_source" : {
"date": "2014-09-24",
...
},
"sort" : [ 1411516800000 ]
},
...
}
- _score 不被計(jì)算, 因?yàn)樗]有用于排序。
- date 字段的值表示為自 epoch (January 1, 1970 00:00:00 UTC)以來的毫秒數(shù),通過 sort 字段的值進(jìn)行返回。
- 計(jì)算 _score 的花銷巨大,通常僅用于排序; 我們并不根據(jù)相關(guān)性排序,所以記錄 _score 是沒有意義的。如果無論如何你都要計(jì)算 _score , 你可以將 track_scores 參數(shù)設(shè)置為 true 。
-
多級(jí)排序
假定我們想要結(jié)合使用 date 和 _score 進(jìn)行查詢,并且匹配的結(jié)果首先按照日期排序,然后按照相關(guān)性排序:
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
-
字段多值排序
一種情形是字段有多個(gè)值的排序, 需要記住這些值并沒有固有的順序;一個(gè)多值的字段僅僅是多個(gè)值的包裝,這時(shí)應(yīng)該選擇哪個(gè)進(jìn)行排序呢?
對(duì)于數(shù)字或日期,你可以將多值字段減為單值,這可以通過使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每個(gè) date 字段中的最早日期進(jìn)行排序,通過以下方法:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
字段排序與多字段
被解析的字符串字段也是多值字段, 但是很少會(huì)按照你想要的方式進(jìn)行排序。如果你想分析一個(gè)字符串,如 fine old art , 這包含 3 項(xiàng)。我們很可能想要按第一項(xiàng)的字母排序,然后按第二項(xiàng)的字母排序,諸如此類,但是 Elasticsearch 在排序過程中沒有這樣的信息。
為了以字符串字段進(jìn)行排序,這個(gè)字段應(yīng)僅包含一項(xiàng): 整個(gè) not_analyzed 字符串。 但是我們?nèi)孕枰?analyzed 字段,這樣才能以全文進(jìn)行查詢
一個(gè)簡(jiǎn)單的方法是用兩種方式對(duì)同一個(gè)字符串進(jìn)行索引,這將在文檔中包括兩個(gè)字段: analyzed 用于搜索, not_analyzed 用于排序
但是保存相同的字符串兩次在 _source 字段是浪費(fèi)空間的。 我們真正想要做的是傳遞一個(gè) 單字段 但是卻用兩種方式索引它。所有的 _core_field 類型 (strings, numbers, Booleans, dates) 接收一個(gè) fields 參數(shù)
該參數(shù)允許你轉(zhuǎn)化一個(gè)簡(jiǎn)單的映射如:
"tweet": {
"type": "string",
"analyzer": "english"
}
為一個(gè)多字段映射如
"tweet": {
"type": "string",
"analyzer": "english",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
什么是相關(guān)性
Elasticsearch 的相似度算法 被定義為檢索詞頻率/反向文檔頻率, TF/IDF 。