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

相关推荐
BillKu29 分钟前
Spring Boot 3中JWT密钥安全存储方案
spring boot·后端·安全
找不到、了1 小时前
Java设计模式之《原型模式》--深、浅copy
java·设计模式·原型模式
独泪了无痕1 小时前
一文搞懂MyBatis中的TypeHandler
数据库·后端·mybatis
程序员岳焱2 小时前
Java 调用 Python 脚本:实现 HelloWorld
java·后端·python
etcix3 小时前
wrap cpp variant as dll for c to use
java·c语言·开发语言
我在北国不背锅4 小时前
基于Java的Markdown转Word工具(标题、段落、表格、Echarts图等)
java·word·echarts·markdown
pengzhuofan4 小时前
Java设计模式-建造者模式
java·设计模式·建造者模式
独行soc4 小时前
2025年大模型安全岗的面试汇总(题目+回答)
android·人工智能·安全·面试·职场和发展·渗透测试
快乐就是哈哈哈4 小时前
Java 短信验证码实战:发送、验证、防刷一步到位
后端