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

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
博客园 - 叶小钗
AI
AI
T
Tor Project blog
Forbes - Security
Forbes - Security
W
WeLiveSecurity
博客园_首页
爱范儿
爱范儿
J
Java Code Geeks
B
Blog
G
GRAHAM CLULEY
aimingoo的专栏
aimingoo的专栏
Cloudbric
Cloudbric
C
CXSECURITY Database RSS Feed - CXSecurity.com
TaoSecurity Blog
TaoSecurity Blog
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
有赞技术团队
有赞技术团队
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
Google DeepMind News
Google DeepMind News
H
Help Net Security
博客园 - 三生石上(FineUI控件)
C
Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 司徒正美
The Last Watchdog
The Last Watchdog
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
S
Secure Thoughts
Spread Privacy
Spread Privacy
F
Fortinet All Blogs
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
Security Latest
Security Latest
Webroot Blog
Webroot Blog
Scott Helme
Scott Helme
Hugging Face - Blog
Hugging Face - Blog

博客园 - 欢乐豆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"
        ]
      }
    ]
  }
}