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

相关推荐
二月夜7 小时前
剖析Java正则表达式回溯问题
java·正则表达式
xuhaoyu_cpp_java8 小时前
项目学习(三)分页查询
java·经验分享·笔记·学习
程序员二叉8 小时前
【Java】集合面试全套精讲|HashMap/ArrayList高频考点完整版
java·面试·哈希算法
cfm_29149 小时前
JVM GC垃圾回收初步了解
java·开发语言·jvm
心之伊始9 小时前
LangChain4j RAG 实战:Java 后端如何把本地文档接入 Embedding 检索链路
java·架构·源码分析·csdn
许彰午9 小时前
17_synchronized关键字深度解析
java·开发语言
阿正的梦工坊9 小时前
【Rust】02-变量、不可变性与基础类型
开发语言·后端·rust
不懂数据的小白10 小时前
面试题一:【三】AB实验入门(验证)
面试
Xzh042311 小时前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
我叫黑大帅11 小时前
通过php 中的Route:: 的写法了解什么是静态类调用
后端·面试·php