ElasticSearch Boost 归档并按日期排序



我正在尝试按字段提升查询,然后按日期对它们进行排序:

multiMatchQuery.fields(columnSortOrder());
searchSourceBuilder.trackScores(true);
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
searchSourceBuilder.sort("updated_time",SortOrder.DESC);

当我执行它时,按列返回结果提升。我想通过两个最高归档订单的组合 按日期排序

提升订单

Field_A^3
Field_B^2
Field_C^1

示例数据:

{
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Slovakia beyond",
"filed_B": "The properties in Slovakia are beyound...",
"Field_C": "Once you fix the relevance then sorting should work correctly."
}
{
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "**beyond** filed_A",
"filed_B": "The properties in Japan is high",
"Field_C": "Test description for filed_A"
}
{
"_score": 2.56865,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B",
"Field_C": "Test description for filed_B"
}
{
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B Test for Feb",
"Field_C": "Test description for filed_B test for Feb"
}
{
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Search Term filed_C",
"filed_B": " is the search term for lowest column",
"Field_C": "**beyond** Test description for filed_C "
}

假设搜索词为"超出" 如果在 [field_A,field_B,filed_C] 中找到搜索词 预期结果为:

[第一优先级Field_A按日期排序]

  1. 2020年1月之后的斯洛伐克
  2. 2020年2月filed_A日之后

[第二优先级Field_B按日期排序]

  1. beyond是2020年1月filed_B日的搜索词
  2. 超越是2020年2月filed_B测试中的搜索词

[第三优先级Field_C按日期排序]

  1. Beyond 2020 年 2 月 filed_C 日的测试说明

可能是因为这个

对字段进行排序时,不会计算分数。通过将track_scores设置为 true,仍会计算和跟踪分数。

因此,请为您的查询启用track_scores

爪哇接口

使用带有参数化变体的曲目分数。

当我尝试使用示例数据时,还需要按分数排序。

{
"_score": {
"order": "desc"
}
}

将其添加为第一个排序,然后按 DESC 日期排序。它的工作原理如下。

如果搜索词是多个字段 [field1, field2, field3] 的一部分,则将计算组合分数。

有几种方法可以做到这一点。使用多个查询(使用多搜索 API(的方法更简洁,对单个查询(使用function_score查询(使用更复杂的方法。让我解释一下如何。

使用_msearch的更清洁的方法

简单地说,_msearch允许发出一个包含多个Elasticsearch查询的HTTP请求。我建议将初始查询拆分为多个查询并按日期排序。这种方法会更简单,因为正如我稍后将向您展示的那样,将其放入一个查询中将需要修改评分,这不是一件容易的事情。

您也可以在不使用_msearch的情况下提出多个请求,无论您认为合适。

为什么其他方法不起作用?

您已经知道通过将某些字段提升到其他字段之上来简化分数优化,如以下示例multi_match查询所示:

POST /myscores/_search
{
"query": {
"multi_match": {
"query": "beyond",
"fields": ["field_A^3", "filed_B^2", "Field_C^1"]
}
}
}

如果匹配field_A,这将简单地取比赛乘以 3 的分数,如果匹配filed_B则乘以 2,依此类推。

现在,分数只是一个真正的正数,它需要表示我们应该在匹配结果列表中放置特定文档的位置。

正如您已经尝试过的,如果您要求 Elasticsearch 使用updated_time作为排序度量,它将忽略匹配中的分数,这是不希望的。

吉布斯同事的建议似乎也行不通,因为使用按_score排序,然后按updated_time排序(反之亦然(忽略了一个或另一个选项。

有没有办法将_scoreupdated_time结合起来?

有,让我们尝试使用function_score

POST /myscores/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "beyond",
"fields": [
"field_A^3",
"filed_B^2",
"Field_C"
]
}
},
"score_mode": "max",     
"boost_mode": "multiply", <=== 2
"field_value_factor": {   <=== 1
"field": "updated_time",   
"factor": 0.00000000001,
"missing": 1
}
}
}
}

function_score允许您微调查询的分数。

我们从上一节中获取我们已经熟悉multi_match查询,并尝试对其进行修改。

首先,我们知道我们希望它考虑到updated_time.我们使用field_value_factor作为函数来修改分数(上面查询中的第 1 点(。

现在,我们告诉它通过将boost_mode设置为multiply来乘以updated_time的值和查询的分数(第 2 点(。

执行此查询将生成如下所示的内容:

"hits": [
{
...
"_score": 43.121338,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "**beyond** filed_A",
"filed_B": "The properties in Japan is high",
"Field_C": "Test description for filed_A"
}
},
{
...
"_score": 43.048275,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Slovakia beyond",
"filed_B": "The properties in Slovakia are beyound...",
"Field_C": "Once you fix the relevance then sorting should work correctly."
}
},
{
...
"_score": 29.028637,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B",
"Field_C": "Test description for filed_B"
}
},
{
...
"_score": 24.44329,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B Test for Feb",
"Field_C": "Test description for filed_B test for Feb"
}
},
{
...
"_score": 23.517717,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Search Term filed_C",
"filed_B": " is the search term for lowest column",
"Field_C": "**beyond** Test description for filed_C "
}
}
] 

请注意,field_A比赛的分数彼此接近,但与filed_B的分数稍远。

另请注意,按updated_time排序的顺序首先是最新的;我们现在将处理相反的顺序。

如何使用updated_time以相反的顺序排序?

field_value_factor允许将字段中的原始值乘以某个因子。

在内部,Elasticsearch将日期存储为unix时间戳。它是一个 10 位数字的整数,实际上比 ES 返回我的分数大 ~10 个数量级。所以我选择将它们按可比顺序排列:

"field_value_factor": {
"field": "updated_time",   
"factor": 0.00000000001,
"missing": 1
}

现在,这给了我们一个等价物SORT BY updated_time DESC

Feb 2020
Jan 2020

但是,如果我们需要它SORT BY updated_time ASC呢?

Jan 2020
Feb 2020

我们不能乘以负因素,因为 Elasticsearch 中的分数必须是正实数。

相反,我们可以做的是使用1/x修改原始值,如下所示:

"field_value_factor": {
"field": "updated_time",
"factor": 0.00000000001,
"missing": 1,
"modifier": "reciprocal"  <=== 1/x
}

这最终会给我们您在问题中要求的顺序:

"hits": [
{
...
"_score": 0.17285699,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Slovakia beyond",
"filed_B": "The properties in Slovakia are beyound...",
"Field_C": "Once you fix the relevance then sorting should work correctly."
}
},
{
...
"_score": 0.1725641,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "**beyond** filed_A",
"filed_B": "The properties in Japan is high",
"Field_C": "Test description for filed_A"
}
},
{
...
"_score": 0.116562225,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B",
"Field_C": "Test description for filed_B"
}
},
{
...
"_score": 0.0978178,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search  term in filed_B Test for Feb",
"Field_C": "Test description for filed_B test for Feb"
}
},
{
...
"_score": 0.09411382,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Search Term filed_C",
"filed_B": " is the search term for lowest column",
"Field_C": "**beyond** Test description for filed_C "
}
}

如何在Java中做到这一点?

虽然我不能为您提供现成的代码,但我相信您可以从 FunctionScoreBuilder 开始,并尝试将其与您现有的代码集成。


希望这有帮助!

相关内容

  • 没有找到相关文章

最新更新