我有一个索引,该索引的映射类似于
{
"id": {
"type": "long"
},
"start": {
"type": "date"
},
"end": {
"type": "date"
}
}
我想创建一个日期直方图,以便每个文档都落入“开始”和“结束”之间的所有存储桶中。
例如。如果对于一个文档,“开始” = 12/01/2018,“结束” = 04/25/2019,我的日期-直方图间隔是几周,范围是从现在到现在的1y。我现在希望文档从2018年12月1日开始的一周直到2019年4月25日这一周进入每个分支。因此,仅凭此一个文档,结果应该是52个存储桶,其中从4月到12月的存储桶的doc_count为0,而从12月到4月的存储桶的doc_count为1。
正如我看到的那样,日期直方图仅使我可以选择根据一个字段(“开始”或“结束”)将我的文档精确匹配到一个存储桶。
到目前为止,我已经尝试过:
两种溶液都非常慢。我正在处理大约20万个文档,而此类查询大约花了10秒钟。
编辑:这是动态生成的示例查询。可以看出,每周创建一个过滤器。该查询大约需要10秒,这很长
%{
aggs: %{
count_chart: %{
aggs: %{
last_seen_over_time: %{
filters: %{
filters: %{
"2018-09-24T00:00:00Z" => %{
bool: %{
must: [
%{range: %{start: %{lte: "2018-09-24T00:00:00Z"}}},
%{range: %{end: %{gte: "2018-09-17T00:00:00Z"}}}
]
}
},
"2018-12-24T00:00:00Z" => %{
bool: %{
must: [
%{range: %{start: %{lte: "2018-12-24T00:00:00Z"}}},
%{range: %{end: %{gte: "2018-12-17T00:00:00Z"}}}
]
}
},
"2019-04-01T00:00:00Z" => %{
bool: %{
must: [
%{range: %{start: %{lte: "2019-04-01T00:00:00Z"}}},
%{range: %{end: %{gte: "2019-03-25T00:00:00Z"}}}
]
}
}, ...
}
}
}
},
size: 0
}
示例响应:
%{
"_shards" => %{"failed" => 0, "skipped" => 0, "successful" => 5, "total" => 5},
"aggregations" => %{
"count_chart" => %{
"doc_count" => 944542,
"last_seen_over_time" => %{
"buckets" => %{
"2018-09-24T00:00:00Z" => %{"doc_count" => 52212},
"2018-12-24T00:00:00Z" => %{"doc_count" => 138509},
"2019-04-01T00:00:00Z" => %{"doc_count" => 119634},
...
}
}
}
},
"hits" => %{"hits" => [], "max_score" => 0.0, "total" => 14161812},
"timed_out" => false,
"took" => 2505
}
我希望这个问题是可以理解的。如果没有,我会更详细地解释。
答案 0 :(得分:1)
如何进行2个date_histogram查询并计算每周差异? 我假设由于查询中的大小为0,您只需要总体计数即可。
let start = await client.search({
index: 'dates',
size: 0,
body: {
"aggs" : {
"start": {
"date_histogram": {
"field": "start",
"interval": "week"
},
}
}
}
});
let end = await client.search({
index: 'dates',
size: 0,
body: {
"aggs" : {
"end": {
"date_histogram": {
"field": "end",
"interval": "week"
},
}
}
}
});
let buckets = {};
let start_buckets = start.aggregations.start.buckets;
let end_buckets = end.aggregations.start.buckets;
let started = 0;
let ended = 0;
for (let i = 0; i < start_buckets.length; i++) {
started += start_buckets[i].doc_count;
buckets[start_buckets[i].key_as_string] = started - ended;
ended += end_buckets[i].doc_count;
}
此测试在我本地进行的时间不到2秒,与您的规模相似。
您可以同时运行两个聚合以节省更多时间。