自從使用 ElasticSearch 重構了主站的搜索項目之后,之后又陸續接入了其他兩個項目,目前使用 SpringBoot 方式跑了一個偽集群,主站使用的時候,比較穩定,沒有人反饋說有問題。
但新接入的一個站點商務反饋說,搜索不夠准確,完全匹配的關鍵詞不是排在搜索結果列表首位,跑到搜索上去看了一眼,確實完全匹配的結果分數不是最高的,導致沒有排在結果首位,今天就來解決這個問題。
默認匹配查詢
先看看我之前寫的查詢代碼片段,
MultiMatchQueryBuilder matchQuery = QueryBuilders.multiMatchQuery(query.getQueryString(), "name", "author");
boolQuery.must(matchQuery);
這種寫法,完全沒有對搜索結果的平分進行干擾,只是按照 ES 的默認分詞計算匹配度的結果。
權重查詢
我嘗試了使用權重查詢,即提升某些字段的權重,但是設置之后,結果反而更加不盡如人意。
boolQuery.should(QueryBuilders.matchQuery("name", queryString).boost(3.0f));
boolQuery.should(QueryBuilders.matchQuery("author", queryString).boost(1.f));
這樣進行查詢之后,如果想要查詢作者,但是作品名稱的權重更高些,所以完全匹配的作者也被排在了后面。
最佳字段查詢
看了官方博客和一篇博客文章,發現 multi-match-query
的高級查詢方式。
multi_match
多匹配查詢的類型有多種,其中的三種恰巧與 了解我們的數據 中介紹的三個場景對應,即:best_fields
、most_fields
和cross_fields
(最佳字段、多數字段、跨字段)。
這里我們想要搜索時,完全匹配的關鍵字排名更靠前,所以這里使用最佳字段 best_fields 進行查詢
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders
.multiMatchQuery(queryString, "name", "author")
.type(MultiMatchQueryBuilder.Type.BEST_FIELDS)
.tieBreaker(0.1f);
boolQuery.must(multiMatchQuery);
首先設置 type 為 BEST_FIELDS,其次,我們想要完全匹配的分數高點,那么就讓沒有完全匹配的分文檔評分低即可,我這里乘以了 0.1 的系數,系數的范圍是 0-1 之間。
加上了系數之后,不完全匹配的文檔評分就被拉開了,就達到了我的最終目的。