ElasticSearch 8.0脚本评分查询

使用脚本来提供返回的文档的自定义评分

script_score查询非常有用,例如:评分函数成本比较高且我们仅仅需要计算一组过滤后的文档的评分。

请求的样例:

下面的script_score查询设置每个返回的文档的评分等于my-int字段值除以10

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

script_score的顶级参数:

query:必须存在,定义查询对象,用于查询需要返回的文档

script:必须存在,定义脚本对象,脚本用于计算查询返回的文档的评分

(备注:通过script_score查询计算的相关评分不能是负数,为了支持特定的查询优化,Lucene要求评分必须是正数或者0)

min_score:可选,浮点型数值,当文档的评分低于此值的时候,将会被从搜索的结果中排除

boost:可选,浮点型数值,脚本生成的文档分数乘以此值生成最终文档分数。默认值为1.0

注意事项:

在脚本里面使用相关性评分

     可以在脚本里面使用_score变量来获取当前文档的相关性评分

预定义函数

     我们可以在脚本里面使用任何可用的painless函数,也看有使用下列的预定义函数来自定义评分:

  • Saturation
  • Sigmoid
  • Random score function
  • Decay functions for numeric fields
  • Decay functions for geo fields
  • Decay functions for date fields
  • Functions for vector fields

官方建议使用这些预定义函数而不是我们自己来写,这些函数ES官方进行了相关优化。

Saturation

saturation(value,k) = value/(k + value)

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

Sigmoidedit
sigmoid(value, k, a) = value^a/ (k^a + value^a)

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

随机评分函数

random_score函数生成从0到但不包括1的均匀分布分数。

random_score函数遵循这样的语法:randomScore(<seed>, <fieldName>)。seed是必须要有的参数,seed是一个整数值,filedName是一个可选参数,是字符型参数。

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

如果filedName参数没有设置,则在内部,Lucene文档的id将会被使用。这将会非常高效,但不幸的是,由于文档可能会被合并重新编号,因此无法复用。

"script" : {
    "source" : "randomScore(100)"
}

需要注意的是,位于同一分片中且字段值相同的文档将获得相同的分数,因此通常需要使用一个字段,该字段对整个分片中的所有文档都具有唯一的值。一个好的默认选择可能是使用_seq_no字段,它唯一的缺点是,如果文档被更新,分数将发生变化,因为更新操作也会更新_seq_no字段的值。

数值字段的衰减函数

  • double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue)
  • double decayNumericExp(double origin, double scale, double offset, double decay, double docValue)
  • double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)
"script" : {
    "source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
    "params": { 
        "origin": 20,
        "scale": 10,
        "decay" : 0.5,
        "offset" : 0
    }
}

备注:脚本只会编译一次,即使后续params会改变。

GEO字段的衰减函数

  • double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
  • double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
  • double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
"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
    }
}

date字段的衰减函数

  • double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
  • double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
  • double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
"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进行计算。

向量类型的函数:

CSDN

开启耗时的脚本查询

如果search.allow_expensive_queries参数被设置为false,则脚本查询不会被执行。

执行计划:

通过explain请求可以看到评分是如何计算的。

script_score查询可以通过设置explanation参数来查看它的执行计划:

GET /my-index-000001/_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;
        """
      }
    }
  }
}

执行_search请求时explanation 的值是null,为了避免出现空指针的情况,需要增加一下判断。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 Spring Boot 操作 Elasticsearch 7.6 进行 SQL 查询的示例代码: 1. 添加 ElasticsearchElasticsearch SQL 依赖库到 pom.xml 文件中: ```xml <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.6.0</version> </dependency> <dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>x-pack-sql-jdbc</artifactId> <version>7.6.0</version> </dependency> ``` 2. 配置 Elasticsearch client: ```java @Configuration public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @Bean public RestHighLevelClient client() { RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, "http")); return new RestHighLevelClient(builder); } } ``` 3. 编写 SQL 查询代码: ```java @Service public class ElasticsearchService { @Autowired private RestHighLevelClient client; public void sqlQuery() throws IOException, SQLException { String sql = "SELECT * FROM my_index WHERE age > 30"; PreparedStatement statement = client.sql().prepareStatement(sql); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getString("name") + " - " + resultSet.getInt("age")); } } } ``` 在上面的代码中,我们使用 `RestHighLevelClient` 对象调用 `sql()` 方法生成 `PreparedStatement` 对象,然后执行 SQL 查询并遍历结果集。 4. 在 application.properties 文件中配置 Elasticsearch 地址和端口号: ``` elasticsearch.host=localhost elasticsearch.port=9200 ``` 这样,我们就可以使用 Spring Boot 操作 Elasticsearch 7.6 进行 SQL 查询了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值