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 

假设你的SchemaExampleSchema

 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 }