【问题标题】:How to specifiy "precision" when sorting on date fields in Elasticsearch?在 Elasticsearch 中对日期字段进行排序时如何指定“精度”?
【发布时间】:2016-01-21 19:55:06
【问题描述】:

我的 Elasticsearch 映射中有一个 date 类型的字段(输入格式 epoch_second)(我使用的是 ES 2.1)。我知道我可以像这样对那个字段进行排序

{
  "sort": [
    {
       "myDateField" : {
         "order": "desc"
        }
    }
  ]
}

但这以秒为单位进行排序。我想按“周间隔”(从现在开始向后间隔 7 天)排序,并在同一周内再次按分数排序,如下所示(伪代码):

{
  "sort": [
    {
       "myDateField" : {
         "order"     : "desc",
         "precision" : "week"
        }
    },
    "_score"
  ]
}

因此,最近 7 天内的所有匹配都应在下一个“排序组”中排名相同,所有早于 7 天且小于 14 天的匹配以此类推。并且每个“周组”都应该再次按分数排序。

简单地说:“过去 7 天中(与当前查询最相关的)文档是什么(但不要完全过滤掉旧的)?”

背景:事件搜索,显然最近的事件最重要。

我怎样才能做到这一点?

【问题讨论】:

  • 看起来你正试图在 sql 中创建类似 Group BY 的东西,它在弹性搜索中同样聚合如何检查 elastic.co/guide/en/elasticsearch/reference/current/… 这个?
  • 但由于性能原因,聚合不支持分页 (github.com/elastic/elasticsearch/issues/4915)。
  • 这确实是一种解决方法,通过排序可能会为您提供更好的解决方案,但如果它仍然吸引您,请检查该评论,它看起来不错github.com/elastic/elasticsearch/issues/…
  • 我的案例可以通过脚本实现吗?我从未使用过脚本,所以我不知道这是否可能以及整个脚本功能提供了多少功能。我记得看到过一些例子,人们根据脚本对字段进行排序,而不是直接在该字段上排序。
  • 当然,即使有特定的细节,您也可以通过脚本解决您的问题。您还可以在 ES 中添加日期作为星期指针。然后,您可以使用您使用的语言按周汇总数据。我认为 Group By 无法通过 Sort By 实现。因此,如果出于性能考虑,循环内部的数据不大,脚本将解决问题。

标签: sorting elasticsearch


【解决方案1】:

您可能会发现decay function on a function score query 在您的情况下很有用。它专门用于调整文档的得分,因为它的一个字段“更远”是从某个定义的起点开始的。

这适用于日期以及数字和地理点字段。它接受origin 选项,该选项设置比较其他文档的参考日期。方便的是,如果您不提供日期字段的来源,它会默认为当前日期(这应该适用于您的场景)。

您可能希望将 offset 设置为 7 天。这样,过去 7 天的所有文件都将得到同等评分。超出该范围,分数开始下降,具体取决于您使用的衰减函数。

试试这样的:

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "field1": "search goes here"
        }
      },
      "functions": [
        {
          "exp": {
            "myDateField": {
              "offset": "7d", 
              "scale": "14d",
              "decay": 0.5
            }
          }
        }
      ]
    }
  }
}

【讨论】:

    【解决方案2】:

    我阅读了有关脚本排序的信息,这是我的解决方案,适合我:

    {
      "sort": [
        "_script": {
          "lang": "expression",
          "type": "number",
          "script": "doc['myDateField'].value - doc['myDateField'].value % 604800000"
          "order": "desc"
        },
        "_score"
      ]
    }
    

    我在这里所做的是将我的日期字段除以以毫秒表示的所需跨度(Elasticsearch 在内部将日期字段存储为long,映射到毫秒)并取余数。然后从实际日期中减去余数。这样,所有日期都被截断为“前(0 到 6)天的上午 0 点”。这样,相同 7 天间隔内的所有文档将具有相同的时间戳,并根据它进行同等排序。最后,我将常规分数排序附加为二阶条件。

    我不确定此解决方案的性能如何扩展,但对于需要此排序的几千个文档,我无法注意到非排序的任何延迟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 2011-07-11
      • 1970-01-01
      相关资源
      最近更新 更多