惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
Schneier on Security
Schneier on Security
T
Tor Project blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Security Latest
Security Latest
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU
L
Lohrmann on Cybersecurity
Scott Helme
Scott Helme
Webroot Blog
Webroot Blog
Project Zero
Project Zero
Google Online Security Blog
Google Online Security Blog
The Last Watchdog
The Last Watchdog
Spread Privacy
Spread Privacy
Hacker News: Ask HN
Hacker News: Ask HN
PCI Perspectives
PCI Perspectives
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News | PayPal Newsroom
Help Net Security
Help Net Security
The Hacker News
The Hacker News
H
Heimdal Security Blog
O
OpenAI News
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
Cyberwarzone
Cyberwarzone
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 叶小钗
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
I
Intezer
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security Affairs
P
Proofpoint News Feed
S
Secure Thoughts
腾讯CDC
Google DeepMind News
Google DeepMind News
量子位
罗磊的独立博客

博客园 - 欢乐豆123

软件设计师考试 - 有限自动机 软件设计师考试 - 排序算法 哈夫曼树以及哈夫曼编码 软件设计师案例题型 - DFD(数据流图) 软件设计师考试 - 二分查找 软件设计师考试 - Gantt图与PERT图(项目管理) 软件设计师考试 - 数据表示(原码、反码、补码、移码) 软件设计师考试 - 上午题型分析 软件设计师考试 - 下午题型分析 软件设计师考试-应用技术 内存溢出问题 常见的算法类型 排序算法的介绍 微信生态梳理 海明码介绍 Nexus的简单介绍以及如何上传自定义包 设计模式-桥接模式(Bridge Pattern) 设计模式简介 jmeter压测 sdkman-管理多个版本的JDK SpringBoot中使用Aop统一拦截MQ消息处理 项目管理流程以及规范 Java-泛型的使用
Elasticsearch 实战:基于 function_score 的搜索与权重排序
欢乐豆123 · 2025-09-16 · via 博客园 - 欢乐豆123

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"
        ]
      }
    ]
  }
}