我有以下文档结构(本例简化)
{
_id : ObjectId("sdfsdf"),
result : [1, 3, 5, 7, 9]
},
{
_id : ObjectId("asdref"),
result : [2, 4, 6, 8, 10]
}
我想得到那些result
数组的总和,但不是总和,而是一个新元素,对应于元素基础上原始数组的总和,即
result : [3, 7, 11, 15, 19]
我在这里搜索过无数问题,其中一些问题已接近尾声(例如this one,this one和this one),但我无法到达那里。< / p>
我可以得到每个数组的总和
aggregate(
[
{
"$unwind" : "$result"
},
{
"$group": {
"_id": "$_id",
"results" : { "$sum" : "$result"}
}
}
]
)
给了我
[ { _id: sdfsdf, results: 25 },
{ _id: asdref, results: 30 } ]
但我无法弄清楚如何获得每个元素的总和
答案 0 :(得分:5)
如果你有3.2或更新的MongoDb,你可以使用includeArrayIndex。
然后你应该改变$unwind
。
您的代码应该是这样的:
.aggregate(
[
{
"$unwind" : { path: "$result", includeArrayIndex: "arrayIndex" }
},
{
"$group": {
"_id": "$arrayIndex",
"results" : { "$sum" : "$result"}
}
},
{
$sort: { "_id": 1}
},
{
"$group":{
"_id": null,
"results":{"$push":"$results"}
}
},
{
"$project": {"_id":0,"results":1}
}
]
)
答案 1 :(得分:1)
对此有一种替代方法,但考虑到使用$push
来创建数组数组&#34;然后将MongoDB 3.4中引入的$reduce
应用于$sum
这些数组元素到单个数组结果中:
you may try this:
CREATE TABLE #STATUS
(
[STATUS] INT,
[START] DATE,
[END] DATE
)
INSERT INTO #STATUS
(
[STATUS], [START], [END]
)
VALUES
(32, '20170101', '20170201'),
(32, '20170201', '20170204'),
(1, '20170204', '20170306'),
(1, '20170306', '20170509'),
(32, '20170509', '20170519'),
(32, '20170519', '20170622')
SELECT
A.STATUS
,A.[START]
,B.[END]
FROM #STATUS A
LEFT JOIN #STATUS B
ON A.[STATUS]=B.[STATUS]
AND A.[END]=B.[START]
WHERE B.STATUS IS NOT NULL
db.collection.aggregate([
{ "$group": {
"_id": null,
"result": { "$push": "$result" }
}},
{ "$addFields": {
"result": {
"$reduce": {
"input": "$result",
"initialValue": [],
"in": {
"$map": {
"input": {
"$zip": {
"inputs": [ "$$this", "$$value" ],
"useLongestLength": true
}
},
"as": "el",
"in": { "$sum": "$$el" }
}
}
}
}
}}
])
到$map
中的真正技巧我们使用$zip
操作创建了一个转置的数组列表&#34;成对&#34;对于两个数组输入。
在第一次迭代中,这将获取提供给$reduce
的空数组,并返回&#34;压缩&#34;输出考虑到第一个对象:
"input"
因此[ [0,1], [0,3], [0,5], [0,7], [0,9] ]
会将空数组的useLongestLength
值替换为当前数组的长度,并且&#34; zip&#34;如上所述。
使用$map
处理时,每个元素都受$sum
的约束,其中&#34;减少&#34;返回的结果为:
0
在第二次迭代中,&#34;数组数组中的下一个条目&#34;将由$zip
与之前的&#34;减少&#34;一起提取并处理。内容为:
[ 1, 3, 5, 7, 9 ]
[ [1,2], [3,4], [5,6], [7,8], [9,10] ]
并且因为只有两个数组被推入&#34;阵列数组&#34;这是操作的结束,也是最终的结果。但是否则$reduce
会继续迭代,直到输入的所有数组元素都被处理完毕。
所以在某些情况下,这将是更高效的选项以及您应该使用的内容。但需要注意的是,特别是在使用[ 3, 7, 11, 15, 19 ]
$group
时,您要问的是每个&#34;将$push
内容记录到数组中以获得结果。
这可能是在极端情况下破坏BSON限制的原因,因此在将位置数组内容聚合到大结果上时,最好将$unwind
与null
选项一起使用。< / p>
或者实际上实际上要仔细研究这个过程,特别是如果&#34;位置数组&#34;问题实际上是其他一些&#34;聚合操作&#34;的结果,那么您应该查看用于创建&#34;位置数组&#34;的先前管道阶段。然后考虑一下,如果你想要那些职位&#34;进一步汇总&#34;对于新的总数,那么你实际上应该这样做&#34;之前&#34;获得了位置结果。