Elasticsearch 實戰:基于 function_score 的搜索與權重排序
Elasticsearch 實戰:基于 function_score 的搜索與權重排序
下面基于項目中關于律師筆記的es搜索功能開發,來記錄下es中基于 function_score 的搜索與權重排序在項目中是如何具體應用和實現的。
一、需求內容
項目中有一個功能,簡單描述為:全局搜索公開展示的律師筆記,通過輸入關鍵詞,匹配筆記標題,律師姓名、律所名稱、擅長領域這四個字段,排序規則:點贊數 (由高到低)> 筆記發布時間(由近到遠)> 筆記ID(由大到小)
可以理解為:
搜索內容涉及:筆記標題(title 字段),作為最核心的匹配字段。
律師信息,包括律師姓名(nick_name)、律所名稱(law_firm)和擅長領域(good_at_topic)。這些字段也會影響匹配度,但權重較標題低。
排序優先級:
第一優先級: 根據筆記的“點贊數”(like_count)倒序排列,點贊越多,排序越靠前。
第二優先級: 在點贊數相同時,按筆記的“發布時間”(create_time)倒序排列,最新發布的筆記優先展示。
兜底排序規則:若上述條件均相同,則按 id 主鍵倒序排序。
二、需求分析
1. 擅長領域存入es的是id 數組,需要先通過分詞到主題 topic 索引中查詢 匹配的id數組,再去筆記 note 索引中做筆記查詢
2. 使用 function_score 來給不同匹配條件設置不同權重,提高匹配精準度。( 搜索字段的權重從高到低:標題 > 律師姓名 > 律所名稱 > 擅長領域
3. 通過 Elasticsearch 自帶的排序機制,實現基于 like_count、create_time 和 id 的多級排序。
4. 利用 filter 確保部分條件不影響打分,只作為過濾條件(例如筆記狀態必須為公開)。
三、Java代碼實現
技術背景:java 框架使用springboot 2.6, elasticsearch 8.15,es框架使用的是 easy-es 3.0.0
部分重要代碼示例:
四、DSL查詢示例
筆記 note 索引的Mapping定義:
PUT /note { "settings": { "number_of_shards": 7, "index.max_ngram_diff": 2, "analysis": { "tokenizer": { "ik_smart_tokenizer": { "type": "ik_smart" }, "ngram_tokenizer": { "type": "ngram", "min_gram": 2, "max_gram": 3 } }, "filter": { "ngram_filter": { "type": "ngram", "min_gram": 2, "max_gram": 3 } }, "analyzer": { "ik_ngram_analyzer": { "type": "custom", "tokenizer": "ik_smart_tokenizer", "filter": ["ngram_filter"] }, "ngram_analyzer": { "type": "custom", "tokenizer": "ngram_tokenizer" } } } }, "aliases": { "note_alias": {} }, "mappings": { "properties": { "id": { "type": "keyword" }, "lawyer_id": { "type": "keyword" }, "name": { "type": "keyword"}, "nick_name": { "type": "keyword"}, "law_firm": { "type": "keyword"}, "good_at_topic": { "type": "keyword" }, "head_url": { "type": "keyword" }, "title": { "type": "text", "analyzer": "ik_ngram_analyzer", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "cover": { "type": "keyword" }, "description": { "type": "keyword"}, "type": { "type": "keyword" }, "content": { "type": "keyword" }, "status": { "type": "keyword" }, "top": { "type": "integer" }, "top_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "like_count": { "type": "integer" }, "comment_count": { "type": "integer" }, "collect_count": { "type": "integer" }, "share_count": { "type": "integer" }, "look_count": { "type": "integer" }, "create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "create_by": { "type": "keyword" }, "update_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "update_by": { "type": "keyword" }, "version": { "type": "keyword" } } } }
查詢DSL語句為:
GET /note/_search { "from": 0, "query": { "bool": { "filter": [ // 不參與評分 { "bool": { "must": [ { "term": { "status": { "boost": 1, "value": "PUBLIC" } } } ] } } ], "must": [ { "function_score": { "boost_mode": "multiply", "functions": [ { "filter": { "match": { "title": { "query": "測試" } } }, "weight": 10000 }, { "filter": { "wildcard": { "nick_name": { "value": "*測試*" } } }, "weight": 1000 }, { "filter": { "wildcard": { "law_firm": { "value": "*測試*" } } }, "weight": 100 }, { "filter": { "terms": { "good_at_topic": [] } }, "weight": 10 } ], "min_score": 10, "score_mode": "sum" } } ] } }, "size": 10, "sort": [ { "_score": { "order": "desc" } }, { "like_count": { "order": "desc" } }, { "create_time": { "order": "desc" } }, { "id": { "order": "desc" } } ], "track_total_hits": true }
查詢結果部分內容為:
{ "took": 5, "timed_out": false, "_shards": { "total": 7, "successful": 7, "skipped": 0, "failed": 0 }, "hits": { "total": 136, "max_score": null, "hits": [ { "_index": "note", "_id": "1952978126582046720", "_score": 10100, "_source": { "id": "1952978126582046720", "law_firm": "測試授權企業", "nick_name": "王五", "title": "測試筆記", "like_count": 3, "create_time": "2025-08-06 14:20:45" }, "sort": [ 10100, 2, 1754490045000, "1952978126582046720" ] }, { "_index": "note", "_id": "1896834568167723008", "_score": 10100, "_source": { "id": "1896834568167723008", "law_firm": "測試簽約12", "nick_name": "李六", "title": "805筆記測試", "like_count": 2, "create_time": "2025-03-04 16:06:17" }, "sort": [ 10000, 8, 1741104377000, "1896834568167723008" ] }, { "_index": "note", "_id": "1912125735872598016", "_score": 10000, "_source": { "id": "1912125735872598016", "law_firm": "袁向何律師事務所", "nick_name": "歡樂豆0905", "title": "測試一下", "like_count": 5, "create_time": "2025-04-15 20:47:56" }, "sort": [ 10000, 5, 1744750076000, "1912125735872598016" ] } ] } }

浙公網安備 33010602011771號