mongoose – 取的总和,并添加新的属性到同一个文件
我在Mongo数据库中有以下文件:
{ _id: 1, question: "Blue or red?", __v: 0, votes: [9, 5] }
我想在后端获得总数为14的投票(因为9 + 5 = 14),并dynamic地在该文档上附加一个新的属性。 所以最后它会是这样的:
{ _id: 1, question: "Blue or red?", __v: 0, votes: [9, 5], totalVotes: 14 }
我研究了如何做到这一点,并发现了这样的词汇:聚合,放松等我不认为这些将帮助我,因为在MongoDB聚合比较文件的属性,我只想修改单一文件的内部相对于其本身的属性。
这是我的“尝试”:
var getTotal = function(arr){ var total = 0; for(var i in arr) { total += arr[i]; } return total; }; Model.update({ $set: { totalVotes: getTotal(votes) }}, function(){ console.log('Updated.'); });
显然votes
没有定义,这将导致错误。 我如何告诉它从模型中获得投票,并将其传递给getTotal()
函数?
这是模型的模式,顺便说一句:
question: {type: String, required: true}, votes: [Number], totalVotes: Number
假设你的Schema
是ExampleSchema
var ExampleSchema = new Schema({ question: {type: String, required: true}, votes: [Number] }, { toObject: { virtuals: true }, toJSON: { virtuals: true } });
这将允许在查询mongoDB中的文件时使用virtuals
机
现在在声明模式之后执行虚拟简单。
ExampleSchema .virtual('totalVotes') .get(function () { return this.votes.reduce(function(currentValue, previousValue){ return (currentValue + previousValue); }); });
你也可以使用.aggregate()
方法来做到这一点:
从MongoDB 3.2中,你可以在$project
阶段使用$sum
操作符。 更多信息在文档中 。
Model.aggregate( [ { '$match': { '_id': 1 } }, { "$project": { "totalVotes": { "$sum": "$votes" } }} ], function(err, result) { Model.update( { '_id': result[0]['_id'] }, { '$set': { 'totalVotes': result[0]['totalVotes'] }}, function(){ console.log('Updated.'); } ); } )
在之前的版本中,您需要首先$unwind
“votes”数组。
Model.aggregate( [ { "$match": { "_id": 1 } }, { "$unwind": "$votes" }, { "$group": { "_id": "$_id", "totalVotes": { "$sum": "$votes" } }} ], function(err, result) { Model.update( { '_id': result[0]['_id'] }, { '$set': { 'totalVotes': result[0]['totalVotes'] }}, function(){ console.log('Updated.'); } ); } )
@Minato说我应该尝试一种叫虚拟的东西。 我做了,结果是好的,除了一件事…
这里是文件:
{ _id: 1, question: "Blue or red?", __v: 0, votes: [9, 5] }
我想添加一个名为totalVotes
的值为14
的属性。 (9 + 5 = 14)
所以,考虑这个模式:
var PollSchema = new Schema( { question: {type: String, required: true}, votes: [Number] }, { toObject: { virtuals: true }, toJSON: { virtuals: true } } );
现在,在这个模式下,我添加了虚拟属性:
PollSchema.virtual('totalVotes').get(function() { var total = getTotal(this.votes); return total; });
而且,我得到这个:
{ _id: 1, question: "Blue or red?", __v: 0, votes: [9, 5], totalVotes: "14[object Object]" }
现在,显然,输出是JSON所以“[对象对象]”是string的一部分。 要删除它,我只使用parseInt()
方法…
PollSchema.virtual('totalVotes').get(function() { var total = getTotal(this.votes); return parseInt(total); });
而输出完全是我一直想要的。
{ _id: 1, question: "Blue or red?", __v: 0, votes: [9, 5], totalVotes: 14 }