ElasticSearch Java API 實現 More Like This 內容推薦
基於內容的推薦核心是「以文尋文」。Elasticsearch 封裝了 Lucene MoreLikeThis,提供三種 Java API 調用方式,本文詳細對比並列舉所有可調參數。
基礎查詢 DSL
{
"more_like_this": {
"fields": ["title", "content"],
"like_text": "text like this one"
}
}
fields:匹配字段,默認 _all
like_text:直接提供文本(不需現有文檔 ID)
核心調優參數
| 參數 | 默認值 | 說明 |
| percent_terms_to_match | 0.3 | 匹配詞項百分比 |
| min_term_freq | 2 | 單文檔詞最小頻次,過濾低頻噪聲 |
| max_query_terms | 25 | 查詢最大詞項數,控制性能 |
| stop_words | - | 停用詞集合 |
| min_doc_freq | 0 | 詞項最小文檔頻次,過濾過於常見詞 |
| max_doc_freq | 無限制 | 詞項最大文檔頻次,過濾停用詞 |
| min_word_len | 0 | 最小詞長 |
| max_word_len | 無限制 | 最大詞長 |
| boost_terms | 1.0 | 詞項權重提升 |
| boost | 1.0 | 整體查詢權重 |
| analyzer | 字段映射 | 指定分詞器,默認使用字段映射的 |
三種 Java API 調用方式
方式一:MoreLikeThisRequestBuilder(基於現有文檔 ID)
MoreLikeThisRequestBuilder mlt = new MoreLikeThisRequestBuilder(client, "index", "type", "docId");
mlt.setField("title");
mlt.setField("content");
mlt.setMinTermFreq(1);
mlt.setMaxQueryTerms(12);
SearchResponse response = client.moreLikeThis(mlt.request()).actionGet();
- 直接在
client 上調用 moreLikeThis()
- 適合「推薦與此文檔相似的文檔」場景
方式二:MoreLikeThisQueryBuilder(基於文本,完整參數控制)
MoreLikeThisQueryBuilder query = QueryBuilders.moreLikeThisQuery()
.fields("title", "content")
.likeText("用戶輸入或文檔摘要")
.minTermFreq(1)
.maxQueryTerms(12)
.percentTermsToMatch(0.3f)
.boost(1.0f);
SearchResponse response = client.prepareSearch("index")
.setTypes("type")
.setQuery(query)
.get();
- 鏈式調用,所有參數均有對應 setter
- 可組合進
BoolQuery 等複雜查詢
方式三:MoreLikeThisFieldQueryBuilder(單字段簡化版)
MoreLikeThisFieldQueryBuilder query = QueryBuilders.moreLikeThisFieldQuery("content")
.likeText("文本")
.minTermFreq(1);
- 構造時指定單一字段
- 內部委託給
MoreLikeThisQueryBuilder
選型建議
| 場景 | 推薦方式 |
| 已有文檔 ID,需推薦相似文檔 | 方式一 |
| 無文檔 ID,基於用戶輸入/臨時文本推薦 | 方式二 |
| 單字段匹配,參數極簡 | 方式三 |
| 需組合其他查詢條件(如過濾分類、時間) | 方式二 + BoolQueryBuilder |
最佳實踐提示
like_text 文本應經過同樣分詞器處理,或直接傳入分析後的詞項
- 大規模索引建議設置
max_query_terms 限制查詢擴展規模
- 結合
min_doc_freq/max_doc_freq 過濾無區分度詞項
- 中文場景必須指定
analyzer(如 ik_smart/ik_max_word)