字节二面: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 降序。 🚀

相关推荐
小溪学编程13 小时前
从 C++ 的规范变迁看语言发展
jvm·c++·面试
打工仔折腾 AI13 小时前
从Attention到BERT:双向预训练语言模型到底解决了什么问题
人工智能·后端·python·深度学习·语言模型·bert
谢亮_vipxieliang13 小时前
Stream API 不是银弹:常见坑与性能建议
java·开发语言
源码宝13 小时前
Web‑PACS 云影像源码|Java+Vue3 医院影像管理系统完整方案
java·源码·影像pacs·成品源码·医院影像系统
ShineWinsu14 小时前
对于Redis:string类型的解析
java·c++·redis·分布式·缓存·面试·string
lizhongxuan14 小时前
Agent Sandbox: Firecracker 任务生命周期
后端
YYYing.14 小时前
【设计模式系列 (七) 】桥接模式
c++·后端·设计模式·桥接模式
lizhongxuan15 小时前
Agent Sandbox: Firecracker 镜像、启动与 I/O
后端
三84416 小时前
Fastjson 漏洞 · 02 · autoType 机制与 checkAutoType
java·fastjson