Mongoose — 使用聚合创建具有 $sum 的新属性
Posted
技术标签:
【中文标题】Mongoose — 使用聚合创建具有 $sum 的新属性【英文标题】:Mongoose — Create new property with $sum using aggregation 【发布时间】:2016-04-04 06:16:59 【问题描述】:我正在尝试在所有包含数字数组总和的文档中添加一个新字段。
这是 Schema(为简洁起见,删除了不相关的字段):
var PollSchema = new Schema(
votes: [Number]
);
我建立模型:
PollModel = mongoose.model('Poll', PollSchema);
我使用聚合来创建一个包含投票数组总和的新字段。
PollModel.aggregate([
$project:
totalVotes: $sum: "$votes"
]);
当我启动我的服务器时,我没有收到任何错误;但是,totalVotes
字段尚未创建。我使用this 文档来帮助我。它同样使用$sum
运算符,我完全按照文档说明的方式进行操作,但没有结果。
【问题讨论】:
***.com/questions/5370846/… @Vishnu 我已经定义了架构? 无法获取模型中未定义的字段。这就是问题所在。 @Vishnu 聚合框架的结果不受模型模式的限制,可以是任何东西。所以这不是问题,而是你不能在$project
内应用$sum
,也不能直接在数组上应用。
【参考方案1】:
MongoDb 聚合不会将其结果保存到数据库中。您只需在回调中获得内联聚合的结果。 因此,在聚合之后,您需要对数据库进行多次更新:
PollModel.aggregate([
$project: totalVotes: $sum: "$votes"
]).exec( function(err, docs)
// bulk is used for updating all records within a single query
var bulk = PollModel.collection.initializeUnorderedBulkOp();
// add all update operations to bulk
docs.forEach(function(doc)
bulk.find(_id: doc._id).update($set: totalVotes: doc.totalVotes);
);
// execute all bulk operations
bulk.execute(function(err)
);
)
);
【讨论】:
我认为这不起作用,因为我使用的是 Mongoose【参考方案2】:不幸的是,这并没有像您想象的那样起作用,因为“投票”实际上是一个值数组,其次是因为$sum
是accumulator operator,仅用于$group
管道阶段。
所以为了让你得到数组的总和作为另一个属性,首先你必须$unwind
数组然后$group
一起在文档键上$sum
元素的总和:
PostModel.aggregate(
[
"$unwind": "$votes" ,
"$group":
"_id": "$_id",
"anotherField": "$first": "$anotherField" ,
"totalVotes": "$sum": "$votes"
],
function(err,results)
);
在这里还要注意,$first
中的另一个累加器对于您想要在结果中的每个附加字段是必要的,因为 $group
和 $project
只返回您要求的字段。
通常,出于性能原因,最好将其作为每个文档中的属性保留,因为它比使用聚合更快。因此,要做到这一点,只需在每次 $push
到数组时增加一个总数,同时使用 $inc
:
PostModel.update(
"_id": id ,
"$push": "votes": 5 ,
"$inc": "totalVotes": 5
,
function(err,numAffected)
);
通过这种方式,“totalVotes”字段始终可以使用,而无需解构数组并对每个文档的值求和。
【讨论】:
【参考方案3】:您的架构中没有 totalVotes
。试试下面的代码。
var PollSchema = new Schema(
votes: [Number],
totalVotes: Number
);
PollModel.aggregate([
$project:
totalVotes: $sum: "$votes"
]);
或
resultData.toJSON();
【讨论】:
我试了一下,文档中显示了字段,但是值只是一个空数组 @Matthew 试试更新的代码。totalVotes
应该是一个数字,而不是一个数组:P。【参考方案4】:
@Blakes Seven 和 @Volodymyr Synytskyi 帮助我找到了解决方案!我还发现 this 文档特别有用。
PollModel.aggregate(
[
'$unwind': '$votes' ,
'$group':
'_id': '$_id',
'totalVotes': '$sum': '$votes'
],
function(err,results)
// console.log(results);
results.forEach(function(result)
var conditions = _id: result._id ,
update = totalVotes: result.totalVotes ,
options = multi: true ;
PollModel.update(conditions, update, options, callback);
function callback (err, numAffected)
if(err)
console.error(err);
return;
else
// console.log(numAffected);
);
);
【讨论】:
以上是关于Mongoose — 使用聚合创建具有 $sum 的新属性的主要内容,如果未能解决你的问题,请参考以下文章
mongoDB,带有 $sum 和 $count 的 mongoose 聚合查询
mongoDB,带有 $sum 和 $count 的 mongoose 聚合查询