我有一个文件集,如:
{
_id: 5,
responses: [
{
staff: false,
timestamp: 1000
},
{
staff: true,
timestamp: 1500
}
]
}
我有一个函数(使用$function
),用于对responses
数组应用一些自定义逻辑:
const diffs=[];
let current;
for (let i = 0; i < responses.length; i++) {
if (i+1>=responses.length) break;
if (!current && !responses[i].staff) current = responses[i];
if (!current) continue;
const next = responses[i+1];
if (!next.staff) continue;
diffs.push(next.timestamp - current.timestamp);
current = undefined;
}
return diffs;
它基本上返回数字数组,如[500, 1000, 10]
等。它还可能返回空数组([]
)。
我想把所有数组合并成一个数组(假设一个文档返回[5, 10]
,下一个返回[1, 2]
,结果是[5, 10, 1, 2]
--顺序无关紧要),然后使用$avg
计算平均值。
我在阅读MongoDB文档时发现了$concatArrays
,因此据我所知,该过程应该是:
1.计算每个文档的差异,最后得到一个类似[[1, 2], [3, 4], [5, 6, 7], [], ...]
的数组
1.对步骤1中的值使用$concatArrays
1.对步骤2中的阵列使用$avg
我应该如何进行步骤1?我唯一不确定的部分是如何在第一个分组阶段保存一个变量,并从$function
返回结果。我知道我需要这样做:
aggregate([
{$group: {diffs: {$function: {...}}}}
])
但是,我得到错误MongoServerError: unknown group operator '$function'
。
2条答案
按热度按时间3pmvbmvn1#
最后,我得到了我想要的结果。如果读到原始问题的人对数据有一些困惑的话,我很抱歉--问题的基本要点是,对于每个文档,函数计算一个全是数字的数组(比如
[1, 2, 3]
),我想用所有文档中的所有数字组合成一个大数组,然后用它计算一个平均值。我首先计算每个文档的数组(
diffs
),展开数组,使用$push
将数组中的每个元素推入一个新的元素中,最后在创建的数组上使用$avg
,希望这能帮助遇到类似问题的人。2wnc66cl2#
Documentation表示:
在聚合表达式内执行JavaScript可能会降低性能。仅当提供的管道运算符无法满足应用程序的需要时,才使用
$function
运算符。这是一个起点,可以通过聚合管道在本地实现同样的效果。我没有花太多时间进行测试,但这将是一个方向。
https://mongoplayground.net/p/Ie6IL8atLX-
另一种方法是使用
input: { $range: [ 0, {$subtract: [{ $size: "$responses" }, 1]} ] },
,然后使用{ $arrayElemAt: [ "$responses", "$$this" ] }
访问元素,可能参见this example,这是一个类似的用例。