我在聚合管道上遇到性能问题和内存限制。 我的目标是从“平铺”集合中提取文档,每个图块存储一天中每一分钟的时间序列值,并将其转换为每分钟时间戳键的矩阵单元列表。
这是切片文档的结构:
{
loc: [lng, lat],
hash: [string],
start: [stamp],
hours: {
0: {
mins: {
0: [value],
1: [value],
...,
59: [value]
}
},
1: {
mins: {
0: [value],
1: [value],
...,
59: [value]
}
},
...,
23: {
mins: {
0: [value],
1: [value],
...,
59: [value]
}
}
}
}
这是我希望获得的矩阵列表:
{
1588550400000: {
{
loc: [lng, lat],
val: [value]
},
{
loc: [lng, lat],
val: [value]
},
...
},
1588550460000: {
{
loc: [lng, lat],
val: [value]
},
{
loc: [lng, lat],
val: [value]
},
...
},
...
}
我首先必须提取匹配地理区域和时间范围的文档。
然后我想我应该进行投影,尝试将每个时间序列分解为单独的条目。
空序列有时会出现在这里,这是一个小的条件挑战,它们会作为 null 作为 hours 条目存储在tile文档中。
所以我终于想出了以下管道:
db.getCollection("tiles")
.aggregate([
{
$match: {
loc: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [[
[1.1471651891249255, 43.41692803575214],
[1.1471651891249255, 43.776544207540915],
[1.6436790011343436, 43.776544207540915],
[1.6436790011343436, 43.41692803575214],
[1.1471651891249255, 43.41692803575214]
]]
}
}
},
start: {
$gte: 1588550400000, // 2020-04-05
$lt: 1588636800000
}
}
},
{
$project: {
loc: "$loc",
times: {
$cond: {
if: {$eq: ["$hours", null]},
then: { // Handle a null time series for this cell
$reduce: {
input: {
$map: {
input: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
as: "h",
in: {
$map: {
input: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],
as: "m",
in: {
k: {
$sum: [
1588550400000,
{ $multiply: [3600000, { $toInt: "$$h" }]},
{ $multiply: [60000, { $toInt: "$$m" }] }
]
},
l: "$loc",
v: 0,
}
}
}
}
},
initialValue: [],
in: {
$concatArrays: [ "$$value", "$$this" ]
}
}
},
else: {
$reduce: {
input: {
$map: {
input: {
"$objectToArray": "$hours",
},
as: "h",
in: {
$map: {
input: {
"$objectToArray": "$$h.mins",
},
as: "m",
in: {
k: {
$sum: [
1588550400000,
{ $multiply: [3600000, { $toInt: "$$h.k" }]},
{ $multiply: [60000, { $toInt: "$$m.k" }] }
]
},
l: "$loc",
v: "$$m.v",
}
}
}
}
},
initialValue: [],
in: {
$concatArrays: ["$$value", "$$this"]
}
}
}
}
}
}
},
{ $unwind: "$times" },
{ $group: {
_id: "$times.k",
grid: {
$push: {
loc: "$times.l",
val: "$times.v"
}
}
} },
{ $sort: { _id: 1 } }
],
{allowDiskUse: true});
但是我似乎在展开和 group 阶段达到了极限。
有没有更好的方法来进行这种转换?
我应该在 project / map 阶段尝试 group 吗?
我的最后一个问题是如何简化最后一个管道输出,该输出看起来比我预期的目标结构要复杂一些:
{
1588550400000: {
_id: 1588550400000,
grid: [
{
loc: [lng, lat],
val: [value]
},
{
loc: [lng, lat],
val: [value]
},
...
]
},
1588550460000: {
_id: 1588550460000,
grid: [
{
loc: [lng, lat],
val: [value]
},
{
loc: [lng, lat],
val: [value]
},
...
]
},
...
}
我应该使用 replaceRoot 吗?
感谢您的帮助!