Mongodb 如何为文档中的数组获取$sum?
例如,我有以下文档:Mongodb 如何为文档中的数组获取$sum?,mongodb,nosql-aggregation,Mongodb,Nosql Aggregation,例如,我有以下文档: { "_id" : ObjectId("52ffddd3c69e40174c046d67"), "works" : [ { "service_id" : ObjectId("52ffd576c69e40174c046d64"), "price" : 150, "count" : 3, "items" : [ {
{
"_id" : ObjectId("52ffddd3c69e40174c046d67"),
"works" : [
{
"service_id" : ObjectId("52ffd576c69e40174c046d64"),
"price" : 150,
"count" : 3,
"items" : [
{
"price" : 5,
"amount" : 10
},
{
"price" : 7,
"amount" : 3
}
]
},
{
"service_id" : ObjectId("52ffd56fc69e40174c046d63"),
"price" : 100,
"count" : 2
}
]
}
如果service_id指的是我知道的一些外部文档,则不建议使用,price是工作的价格,count是工作执行的次数,items是所有工作中使用的材料数组。
我需要得到所有工程的总价。我尝试了以下未完成的代码:
db.service_cards.aggregate(
{ $match: {_id: ObjectId("52ffddd3c69e40174c046d67") } },
{ $unwind: "$works" },
{ $project: {
"works.service_id": 1,
"works.price": 1,
"works.count": 1,
"works.items": {
"$cond": [
{ $eq: [ "$works.items", []] },
[{
"price": 0,
"amount": 0
}],
"$works.items"
],
}
} },
{ $project: {
"works.service_id": 1,
"works.price": 1,
"works.count": 1,
"works.items": {
"$ifNull": [
"$works.items",
[{
"price": 0,
"amount": 0
}]
],
}
} },
{ $unwind: "$works.items" },
{ $project: {
"service_id": "$works.service_id",
"price": "$works.price",
"count": "$works.count",
"items_cost": { $multiply: ["$works.items.price", "$works.items.amount"] },
} },
{ $group: {
_id: "$service_id",
"sum_items": { $sum: "$items_cost" },
"price": { $avg: "$price" },
"count": { $avg: "$count" }
} }
)
它实际上并没有对数组求和-它将工作项和项目展开,然后使用$group对未打算的项目求和。但后来我想起来了——可能有两件作品的服务id、数量和价格是相同的,在$unwind和$group之后,我会丢失其中一件,将这两件作品中的物品放在一起
是否有任何方法可以在文档中获取数组$sum,而无需$unwind
编辑:
我希望收到一份没有项目的工程清单,但项目总成本为:
{
"_id" : ObjectId("52ffddd3c69e40174c046d67"),
"works" : [
{
"service_id" : ObjectId("52ffd576c69e40174c046d64"),
"price" : 150,
"count" : 3,
"items_cost" : 71
},
{
"service_id" : ObjectId("52ffd56fc69e40174c046d63"),
"price" : 100,
"count" : 2,
"items_cost": 0
}
]
}
我认为,这不是一个更好的解决方案,但它很短,而且做你想做的事情:
db.service_cards.find().forEach(function (document) {
var works = document.works || [];
var result = [];
works.forEach(function (work) {
var items = work.items || [];
var itemsCost = 0;
items.forEach(function (item) {
itemsCost += item.price * item.amount;
});
var resultObj = {
service_id: work.service_id,
price: work.price,
count: work.count,
items_cost: itemsCost
};
result.push(resultObj);
});
print({
_id: document._id,
works: result
});
})
简短的答案是否定的。长的答案取决于您希望做什么以及作为结果文档接收什么。这在你的问题中还不清楚。也许如果你添加了你想要的和期望的,那么人们可以帮助你解决问题。通过添加,我们的意思是,编辑你的问题,包括这一点,并使事情清楚。