字节二面:Elasticsearch搜索,在搜索用到分词后,返回的第一条可能不是最匹配name的数据,这种如何解决?

文章内容收录到个人网站,方便阅读:hardyfish.top/

资料分享 LangChain实战课

课程链接:time.geekbang.org/column/intr...

资料链接:url81.ctfile.com/f/57345181-...

访问密码:3899

AI大模型项目落地实战

课程链接:time.geekbang.org/column/intr...

资料链接:url81.ctfile.com/f/57345181-...

访问密码:3899

在 Elasticsearch(ES)中:

  • 不分词 时(keyword 类型),可以按照 id 降序排序,结果符合预期。
  • 分词后text 类型),搜索 name,匹配度(_score)可能不准确,返回的第一条可能不是最匹配 name 的数据,导致排序和相关性变差。

核心原因

  • ES 默认使用 BM25 算法计算 _score

    ,分词后:

    • 匹配的单词分布影响评分(词频、文档频率)。
    • 短字段 vs 长字段的评分不同 ,可能短的 name 反而 _score 低。
    • 完全匹配的词可能被打散 ,导致排序不如 keyword 直观。

解决方案

为了解决 分词后 name 匹配度下降 的问题,可以采用以下策略:

1. match_phrase 保证短语匹配

  • match_phrase 要求 完整匹配,并按顺序出现,不会因为单个词的 BM25 计算影响匹配度:
json 复制代码
{
  "query": {
    "match_phrase": {
      "name": "你的搜索词"
    }
  }
}

适用于短语查询,避免被拆分后的单词乱序影响相关性。

2. bool 组合查询,提高精准匹配优先级

  • 结合 term(精准匹配 keyword) 和 match(分词匹配 text),提高完全匹配的权重:
json 复制代码
{
  "query": {
    "bool": {
      "should": [
        { "term": { "name.keyword": "你的搜索词" } },
        { "match": { "name": "你的搜索词" } }
      ]
    }
  }
}

term 让完全匹配的 name.keyword 评分更高,match 兼顾模糊匹配。

3. boost 提高 name 相关性

如果 match 计算的 _score 过低,可以提升 name 权重:

json 复制代码
{
  "query": {
    "match": {
      "name": {
        "query": "你的搜索词",
        "boost": 3
      }
    }
  }
}

提高 name_score 计算中的影响,避免低评分影响排序。

4. function_score 结合 id 排序

如果希望在 匹配度高时,同时按照 id 降序排列

json 复制代码
{
  "query": {
    "function_score": {
      "query": {
        "match": { "name": "你的搜索词" }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "id",
            "factor": 1,
            "modifier": "log1p",
            "missing": 1
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

匹配度相同时,id 大的排前面,不影响 _score 排序。

5. _score + id 组合排序

如果 id 降序比 _score 更重要,可以调整排序:

json 复制代码
{
  "query": {
    "match": { "name": "你的搜索词" }
  },
  "sort": [
    { "_score": "desc" },
    { "id": "desc" }
  ]
}

_score 优先排序,匹配度相同时 id 降序。

最终推荐方案

如果你希望 name 高匹配度优先,同时 id 降序:

json 复制代码
{
  "query": {
    "bool": {
      "should": [
        { "term": { "name.keyword": "你的搜索词" } },
        { "match": { "name": { "query": "你的搜索词", "boost": 2 } } }
      ]
    }
  },
  "sort": [
    { "_score": "desc" },
    { "id": "desc" }
  ]
}

这样可以保证 name 完全匹配的 _score 高,且按 id 降序。 🚀

相关推荐
S***26752 小时前
基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
java·spring boot·后端
马剑威(威哥爱编程)2 小时前
鸿蒙6开发视频播放器的屏幕方向适配问题
java·音视频·harmonyos
JIngJaneIL2 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
V***u4533 小时前
MS SQL Server partition by 函数实战二 编排考场人员
java·服务器·开发语言
这是程序猿3 小时前
基于java的ssm框架旅游在线平台
java·开发语言·spring boot·spring·旅游·旅游在线平台
i***t9193 小时前
基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战
java·spring boot·spring
k***08293 小时前
【监控】spring actuator源码速读
java·spring boot·spring
麦麦鸡腿堡4 小时前
Java_网络编程_InetAddress类与Socket类
java·服务器·网络
@大迁世界4 小时前
相信我兄弟:Cloudflare Rust 的 .unwrap() 方法在 330 多个数据中心引发了恐慌
开发语言·后端·rust
vx_dmxq2114 小时前
【PHP考研互助系统】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·mysql·考研·微信小程序·小程序·php