3.2 Elasticsearch-multi_match、boost、function_score 实战

在这里插入图片描述
3.2 Elasticsearch-multi_match、boost、function_score 实战
——让“搜得到”进化成“搜得准”


  1. 本节目标
    上一节我们把 2000 万商品导入了 ES,但搜索“苹果手机”却把“苹果味手机壳”顶到第一位。本节用 30 行 DSL 把相关性从“玄学”变成“可控”:
    ① multi_match 解决“该匹配哪些字段”;② boost 解决“字段谁更重要”;③ function_score 解决“业务规则怎么加权”。最后给出一套可复制的调参模板,直接搬进生产线。

  1. multi_match:一把梭哈多个字段
    1.1 最朴素的 query_string
    GET /mall/_search
    {“query”:{“query_string”:{“query”:“苹果手机”,“default_field”:“_all”}}}
    ❌ 结果:把 description 里出现“苹果”的袜子排第一,因为 _all 字段里 description 最长,TF 得分高。

1.2 multi_match 三模式

  • best_fields:默认,单字段最高分当最终分
  • most_fields:多字段得分加和,适合同义词冗余
  • cross_fields:把多个字段当成一个大字段,解决“分词跨字段”问题

1.3 实战:商品标题3、卖点2、类目名^1
GET /mall/_search
{
“query”: {
“multi_match”: {
“query”: “苹果手机”,
“fields”: [
“title^3”,
“sell_point^2”,
“category_name^1”
],
“type”: “best_fields”,
“tie_breaker”: 0.3
}
}
}
✅ 效果:iPhone 排到第一,苹果味手机壳降到第 5 页。


  1. boost:细粒度“偏心”权重
    场景:旗舰店商品想加 10% 分,库存为 0 的减 50%。
    ES 的 boost 可在索引期写死,但推荐在查询期用“布尔查询 + boosting”动态调整,避免 re-index。

示例:
GET /mall/_search
{
“query”: {
“boosting”: {
“positive”: {
“multi_match”: {
“query”: “苹果手机”,
“fields”: [“title^3”, “sell_point^2”]
}
},
“negative”: {
“term”: { “stock”: 0 }
},
“negative_boost”: 0.5
}
}
}
解释:先算 positive 得分,若满足 negative 子句,最终得分 *= 0.5。旗舰店加 10% 可用 should + constant_score 再包一层 bool,灵活组合。


  1. function_score:把“业务规则”翻译成“数学公式”
    3.1 四种内置函数
  • weight:简单粗暴乘系数
  • field_value_factor:拿字段值当系数,如销量、评分
  • decay_gauss/linear/exp:地理位置、价格、发布时间衰减
  • script_score:Groovy/Painless 任意脚本,天上地下都能算

3.2 需求拆解
“苹果手机”搜索排序公式:
score = 相关性 * (1 + 销量/10000) * 0.8^days_from_now * 是否现货(1 or 0.5)

3.3 DSL 模板
GET /mall/_search
{
“query”: {
“function_score”: {
“query”: {
“multi_match”: {
“query”: “苹果手机”,
“fields”: [“title^3”, “sell_point^2”],
“type”: “best_fields”
}
},
“functions”: [
{
“field_value_factor”: {
“field”: “sold_num”,
“modifier”: “log1p”,
“factor”: 0.0001
}
},
{
“gauss”: {
“on_shelf_date”: {
“origin”: “now”,
“scale”: “10d”,
“decay”: 0.8
}
}
},
{
“filter”: { “term”: { “stock”: 0 } },
“weight”: 0.5
}
],
“score_mode”: “multiply”,
“boost_mode”: “multiply”
}
}
}
关键参数说明:

  • log1p 避免销量 0 时乘以 0 导致无得分
  • gauss 10 天衰减到 0.8,30 天大约 0.5,可 A/B 测试调 scale
  • weight 0.5 相当于 negative_boost,但可叠加多个 filter

  1. 调参“三板斧”
  1. 解释 API 看分值:?explain=true,快速定位谁拖了后腿
  2. 复制真实请求到 Kibana,改一个参数刷一次,用表格记录
  3. 离线测评:拉 1000 条人工标注 query,计算 NDCG@10,脚本批量跑,一晚出结果

  1. 踩坑清单
    × 滥用 script_score:线上 2000 qps 时,Groovy 编译缓存打满 Young GC,直接 STW 3 s;换 field_value_factor + decay 后 CPU 降 40%
    × 在索引期设置 field boost:后期改权重必须 re-index,曾导致凌晨 4 点全集群重写,被老板请喝茶
    × cross_fields 对“中文+拼音”混合字段失效:记得统一 analyzer,否则“ping guo”匹配不到“苹果”

  1. 一键拷贝模板
    把下面 JSON 存成 search_template.json,后期只改参数即可:
    POST /_scripts/mall_search
    {
    “script”: {
    “lang”: “mustache”,
    “source”: “”"
    {
    “from”: “{{from}}{{^from}}0{{/from}}”,
    “size”: “{{size}}{{^size}}20{{/size}}”,
    “query”: {
    “function_score”: {
    “query”: {
    “multi_match”: {
    “query”: “{{q}}”,
    “fields”: [
    “title{{title_boost}}{{title_boost}}3{{/title_boost}}”,
    “sell_point{{sell_boost}}{{sell_boost}}2{{/sell_boost}}”,
    “category_name^1”
    ],
    “type”: “best_fields”,
    “tie_breaker”: 0.3
    }
    },
    “functions”: [
    {
    “field_value_factor”: {
    “field”: “sold_num”,
    “modifier”: “log1p”,
    “factor”: {{sold_factor}}{{^sold_factor}}0.0001{{/sold_factor}}
    }
    },
    {
    “gauss”: {
    “on_shelf_date”: {
    “origin”: “now”,
    “scale”: “{{new_scale}}{{^new_scale}}10d{{/new_scale}}”,
    “decay”: {{new_decay}}{{^new_decay}}0.8{{/new_decay}}
    }
    }
    }
    ],
    “score_mode”: “multiply”,
    “boost_mode”: “multiply”
    }
    }
    }
    “”"
    }
    }
    调用:
    GET /mall/_search/template
    {
    “id”: “mall_search”,
    “params”: {
    “q”: “苹果手机”,
    “title_boost”: 4,
    “new_scale”: “7d”
    }
    }

  1. 小结
    multi_match 解决“查什么”,boost 解决“谁重要”,function_score 解决“怎么算”。三件套组合后,搜索 PM 再想“把 iPhone 14 置顶”只需调两个数字,而不用凌晨拉集群。下一节我们把这套脚本固化到 Search Template + Index Alias,配合 AB 实验平台,让运营同学也能 5 分钟上线“新品加权 20%”实验。
    更多技术文章见公众号: 大城市小农民
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔丹搞IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值