Elasticsearch之排序與相關(guān)性

排序

為了按照相關(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 ] 
    },
    ...
}
  1. _score 不被計(jì)算, 因?yàn)樗]有用于排序。
  2. date 字段的值表示為自 epoch (January 1, 1970 00:00:00 UTC)以來的毫秒數(shù),通過 sort 字段的值進(jìn)行返回。
  3. 計(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 。

參考資料

Elasticsearch: 權(quán)威指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容