ES相關度排序異常問題

明明標題全字段匹配,但是按照默認的相關度排序卻排到了第三四位,第一位怎麼看都不應該排在最上面。。今天ES文章檢索我遇到了這個問題。

我對文章的title和content字段使用了多字段查詢,一開始我認爲是content字段干擾了整體的相關度,後來使用boost字段加大了title的查詢權重,結果還是一樣的;後來單獨查詢title字段還是一樣的結果,全匹配字段還是排在了下面,這不禁讓我懷疑起了人生。

image-20211112171348671

百度下,隨便點着點着就點到了官網上的一篇文章:被破壞的相關度 ,全文如下

在討論更復雜的 多字段搜索 之前,讓我們先快速解釋一下爲什麼只在主分片上 創建測試索引

用戶會時不時的抱怨無法按相關度排序並提供簡短的重現步驟:用戶索引了一些文檔,運行一個簡單的查詢,然後發現明顯低相關度的結果出現在高相關度結果之上。

爲了理解爲什麼會這樣,可以設想,我們在兩個主分片上創建了索引和總共 10 個文檔,其中 6 個文檔有單詞 foo 。可能是分片 1 有其中 3 個 foo 文檔,而分片 2 有其中另外 3 個文檔,換句話說,所有文檔是均勻分佈存儲的。

什麼是相關度?中,我們描述了 Elasticsearch 默認使用的相似度算法,這個算法叫做 詞頻/逆向文檔頻率 或 TF/IDF 。詞頻是計算某個詞在當前被查詢文檔裏某個字段中出現的頻率,出現的頻率越高,文檔越相關。 逆向文檔頻率某個詞在索引內所有文檔出現的百分數 考慮在內,出現的頻率越高,它的權重就越低。

但是由於性能原因, Elasticsearch 不會計算索引內所有文檔的 IDF 。相反,每個分片會根據 該分片 內的所有文檔計算一個本地 IDF 。

因爲文檔是均勻分佈存儲的,兩個分片的 IDF 是相同的。相反,設想如果有 5 個 foo 文檔存於分片 1 ,而第 6 個文檔存於分片 2 ,在這種場景下, foo 在一個分片裏非常普通(所以不那麼重要),但是在另一個分片裏非常出現很少(所以會顯得更重要)。這些 IDF 之間的差異會導致不正確的結果。

在實際應用中,這並不是一個問題,本地和全局的 IDF 的差異會隨着索引裏文檔數的增多漸漸消失,在真實世界的數據量下,局部的 IDF 會被迅速均化,所以上述問題並不是相關度被破壞所導致的,而是由於數據太少。

爲了測試,我們可以通過兩種方式解決這個問題。第一種是隻在主分片上創建索引,正如 match 查詢 裏介紹的那樣,如果只有一個分片,那麼本地的 IDF 就是 全局的 IDF。

第二個方式就是在搜索請求後添加 ?search_type=dfs_query_then_fetchdfs 是指 分佈式頻率搜索(Distributed Frequency Search) , 它告訴 Elasticsearch ,先分別獲得每個分片本地的 IDF ,然後根據結果再計算整個索引的全局 IDF 。

不要在生產環境上使用 dfs_query_then_fetch 。完全沒有必要。只要有足夠的數據就能保證詞頻是均勻分佈的。沒有理由給每個查詢額外加上 DFS 這步。

看完全文,似懂非懂,能明白大概是分片導致的,有一句話很重要:如果只有一個分片,那麼本地的 IDF 就是 全局的 IDF。

我的索引分了5片,如果只是分了一片的話,是不是就能解決問題了?

首先,刪除索引

DELETE {{es-host}}/cosmo_qdlind_top_search

然後重建索引

PUT {{es-host}}/cosmo_qdlind_top_search
{
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 1,
        "max_result_window": 1000000
    }
}
	

在這裏把分片和副本數量都設置爲1(原來我的分片數量是5)。

然後重建mapping,最後重新導入數據,測試結果就正常了

image-20211112172339963

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章