Elasticsearch Script Score查询深度解析

Elasticsearch Script Score查询深度解析

elasticsearch elasticsearch 项目地址: https://gitcode.com/gh_mirrors/elas/elasticsearch

什么是Script Score查询

Script Score查询是Elasticsearch提供的一种高级查询功能,它允许开发者使用自定义脚本对查询结果进行评分计算。这种查询方式特别适用于需要基于复杂业务逻辑进行文档排序的场景。

核心概念

基本结构

一个Script Score查询包含两个主要部分:

  1. 基础查询(query):用于筛选文档集
  2. 评分脚本(script):对筛选出的文档进行自定义评分
{
  "query": {
    "script_score": {
      "query": { /* 基础查询 */ },
      "script": { /* 评分脚本 */ }
    }
  }
}

评分限制

需要注意的是,Script Score查询的最终评分必须是非负数(≥0),这是Lucene底层的限制要求。

实际应用示例

简单数值计算

假设我们有一个包含"my-int"字段的文档集,我们可以这样计算评分:

GET /_search
{
  "query": {
    "script_score": {
      "query": {"match": {"message": "elasticsearch"}},
      "script": {
        "source": "doc['my-int'].value / 10"
      }
    }
  }
}

这个例子中,每个文档的评分是其"my-int"字段值除以10的结果。

高级参数详解

核心参数

  1. query(必需):基础查询对象
  2. script(必需):评分脚本对象
  3. min_score(可选):过滤低于此评分的文档
  4. boost(可选):评分倍增系数,默认为1.0

脚本中访问评分

在脚本中,可以通过_score变量访问文档的基础相关性评分:

"source": "_score * doc['boost'].value"

内置评分函数

Elasticsearch提供了一系列预定义的评分函数,建议优先使用这些函数而非自定义实现,因为它们经过了性能优化。

1. 饱和函数(Saturation)

公式:value/(k + value)

"script": {
  "source": "saturation(doc['my-int'].value, 1)"
}

2. Sigmoid函数

公式:value^a/(k^a + value^a)

"script": {
  "source": "sigmoid(doc['my-int'].value, 2, 1)"
}

3. 随机评分函数

生成0到1之间的随机评分:

"script": {
  "source": "randomScore(100, '_seq_no')"
}

注意:如果不指定字段名,将使用Lucene内部文档ID作为随机源,但这种方式在文档合并后可能不可重现。

4. 衰减函数

适用于数值、地理位置和日期字段,提供三种衰减模式:

  1. 线性衰减(Linear)
  2. 指数衰减(Exp)
  3. 高斯衰减(Gauss)
数值衰减示例
"script": {
  "source": "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
  "params": {
    "origin": 20,
    "scale": 10,
    "decay": 0.5,
    "offset": 0
  }
}
地理位置衰减示例
"script": {
  "source": "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
  "params": {
    "origin": "40, -70.12",
    "scale": "200km",
    "offset": "0km",
    "decay": 0.2
  }
}
日期衰减示例
"script": {
  "source": "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
  "params": {
    "origin": "2008-01-01T01:00:00Z",
    "scale": "1h",
    "offset": "0",
    "decay": 0.5
  }
}

注意:日期衰减函数不支持"now"计算,且仅限于默认格式和时区。

性能优化建议

  1. 使用参数化脚本:通过params传递变量,避免脚本重新编译
  2. 考虑替代方案:对于简单场景,使用rank_featuredistance_feature查询可能更高效
  3. 避免昂贵查询:当search.allow_expensive_queries设为false时,Script Score查询不会执行

从Function Score迁移

Script Score查询是Function Score查询的简化替代方案。以下是常见迁移模式:

权重(weight)实现

"script": {
  "source": "params.weight * _score",
  "params": {"weight": 2}
}

字段值因子(field_value_factor)实现

"script": {
  "source": "Math.log10(doc['field'].value * params.factor)",
  "params": {"factor": 5}
}

处理缺失字段:

"script": {
  "source": "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
  "params": {"factor": 5}
}

调试技巧

可以通过Explain API查看评分计算详情:

GET /my-index/_explain/0
{
  "query": {
    "script_score": {
      "query": {"match": {"message": "elasticsearch"}},
      "script": {
        "source": """
          long count = doc['count'].value;
          double normalizedCount = count / 10;
          if (explanation != null) {
            explanation.set('normalized count = count / 10 = ' + count + ' / 10 = ' + normalizedCount);
          }
          return normalizedCount;
        """
      }
    }
  }
}

最佳实践:始终检查explanation是否为null,因为普通搜索请求中它不可用。

总结

Script Score查询为Elasticsearch提供了强大的自定义评分能力,特别适合需要复杂业务逻辑排序的场景。通过合理使用内置函数和性能优化技巧,可以在满足业务需求的同时保持良好的查询性能。

elasticsearch elasticsearch 项目地址: https://gitcode.com/gh_mirrors/elas/elasticsearch

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杨洲泳Egerton

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

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

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

打赏作者

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

抵扣说明:

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

余额充值