问题
我有以下架构中的数据:
{
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
}
}
}
}
我看到的唯一替代方法是在脚本中进行整个操作,但是在使用弹性搜索脚本几个小时后,我放弃了这种方法.
最佳答案 我发现这个问题非常有趣.
个人搜索没有带来合理的方法来实现这一点,其中一个原因是你如何定义日期直方图的开始和结束日期(因为它通常使用字段参数来计算这个)?
使用存储桶和管道聚合的更高级的人可能会提供帮助,但我最接近的将是“欺骗”并构建过滤器聚合以实现目标:
{
"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"}}}
]
}
},
...
}
}
}
}
}
不是很漂亮,但可能仍然值得考虑作为更好答案的起点.