如何在Elasticsearch中对日期字段进行排序时指定“精度”?

4

我有一个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,它在 ElasticSearch 中同样是聚合操作。不妨看看这个链接 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-datehistogram-aggregation.html ? - FZE
但是由于性能原因,聚合不支持分页(https://github.com/elastic/elasticsearch/issues/4915)。 - Foo Bar
这只是一个解决方法,也许有更好的排序解决方案适合你,但如果你仍然感兴趣,可以查看一下这个评论,看起来不错。https://github.com/elastic/elasticsearch/issues/4915#issuecomment-69942916 - FZE
我的情况是否可以通过脚本来实现?我从未使用过脚本,所以不知道这是否可能以及整个脚本功能提供了多少特性。我记得看到过一些例子,人们会对一个字段进行脚本操作排序,而不是直接对该字段进行排序。 - Foo Bar
通过脚本编写,您可以解决具体问题。您还可以在ES中添加日期作为一周指针,然后使用您所使用的语言按周聚合数据。我认为无法通过Sort By实现Group By。因此,如果数据不大且不涉及性能问题,则脚本编写将解决该问题。 - FZE
2个回答

4

在你的情况下,您可能会发现函数分数查询中的衰减函数很有用。它专门设计用于调整文档的得分,使其“越远”离某个定义的起始点。

这适用于日期、数字和地理位置字段。它接受一个origin选项,设置其他文档将与之比较的参考日期。方便的是,如果您没有为日期字段提供原点,则默认为当前日期(这应该适用于您的情况)。

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

尝试类似于以下内容:

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

1
我了解到脚本排序,这是我的解决方案,适用于我:

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接