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号