如何在elasticsearch中创建直方图,其中考虑了日期范围

时间:2017-05-19 22:22:38

标签: date elasticsearch range histogram

问题

我有以下架构中的数据:

{
  start_date: '2017-01-01',
  end_date: '2017-01-05',
},
{
  start_date: '2017-01-03',
  end_date: '2017-01-07',
}

我正在尝试每天创建一个直方图,如果特定文档的开始日期和结束日期日期在当天重叠,则会给我。

根据数据,输出桶将是:

{
  "2017-01-01": { "doc_count": 1 },
  "2017-01-02": { "doc_count": 1 },
  "2017-01-03": { "doc_count": 2 },
  "2017-01-04": { "doc_count": 2 },
  "2017-01-05": { "doc_count": 2 },
  "2017-01-06": { "doc_count": 1 },
  "2017-01-07": { "doc_count": 1 }
}

阅读完所有的elasticsearch聚合文档后,我看不出这是怎么回事。任何帮助表示赞赏。


解决方案

根据Olivier的回答,我做了以下几点:

创建辅助函数以生成开始日期和结束日期之间的所有包含天数:

const generateDateRange = (start, end) => {
  const startDate = moment(start);
  const endDate = moment(end);

  const range = [];

  const date = startDate;
  while (date.isSameOrBefore(endDate)) {
    range.push(date.format('YYYY-MM-DD'));
    date.add(1, 'day');
  }

  return range;
};

创建一个辅助函数,根据日期范围生成聚合所需的所有过滤器:

const generateActivityFilters = (range, options = {}) => {
  const filters = {};

  range.map((date) => {
    filters[date] = {
      bool: {
        filter: [
          { range: { [options.start]: { lte: date } } },
          { range: { [options.end]: { gte: date } } },
        ],
      },
    };
    return true;
  });

  return filters;
};

最后,按如下方式运行查询:

{
  "size": 0, 
  "aggs": {
    "date_histo": {
      "filters": {
        "filters": filters // from generateActivityFilters
      }
    }
  }
}

我看到的唯一替代方法是在script中进行整个操作,但是在使用弹性搜索脚本几个小时后,我放弃了这种方法。

1 个答案:

答案 0 :(得分:2)

我发现这个问题非常有趣。

个人搜索没有带来合理的方法来实现这一点,其中一个原因是你如何定义日期直方图的开始和结束日期(因为它通常使用字段参数来计算)?

使用存储桶和管道聚合的更高级的人可能会提供帮助,但最接近的是“欺骗”并构建过滤器聚合以实现目标:

{
  "size": 0, 
  "aggs": {
    "date_histo": {
      "filters": {
        "filters": {
          "2017-01-01": {
            "bool": {
              "filter": [
                {"range": {"start_date": {"lte": "2017-01-01"}}},
                {"range": {"end_date": {"gte": "2017-01-01"}}}
              ]
            }
          },
          "2017-01-02": {
            "bool": {
              "filter": [
                {"range": {"start_date": {"lte": "2017-01-02"}}},
                {"range": {"end_date": {"gte": "2017-01-02"}}}
              ]
            }
          },
          ...
        }
      }
    }
  }
}

不是很漂亮,但可能仍然值得考虑作为更好答案的起点。

相关问题