2015-11-18 89 views
0

填充在收集现场我有2个猫鼬集合:ExpenseCategory和费用猫鼬:从其他集合

var ExpenseCategorySchema = new Schema({ 
    name: String, 
    totalSpentInThisMonth: Number 
}); 
mongoose.model('ExpenseCategory', ExpenseCategorySchema); 

var ExpenseSchema = new Schema({ 
    expenseCategoryId: {type: Schema.Types.ObjectId, ref: 'ExpenseCategory'}, 
    amount: Number, 
    date: Date 
}); 
mongoose.model('Expense', ExpenseSchema); 

有一个GET api电话写在的Node.js返回所有ExpenseCategory items

appRouter.route('/expensecatgories') 
    .get(function(req, res){ 
     ExpenseCategory.find({}, function (expenseCategories) { 
     res.json(expenseCategories); 
     }); 
    }); 

在上面GET method我想返回之前来填充每个expenseCategories项目现场totalSpentInThisMonth。该字段需要计算为所有expense.amount的总和,其中expense.expenseCategoryIdexpenseCategory.idexpense.date匹配的是当前月份。

如何在返回expenseCategories之前填写字段totalSpentInThisMonth

+0

的可能的复制[如何使用相同的语句填充,并汇总?](http://stackoverflow.com/questions/16680015/how-to-use -populate和聚集型的-相同语句) –

回答

0

使用.aggregate()方法从聚合框架为此。您需要首先构建日期以用作日期范围查询,以查找日期在当前月份内的文档,因此您需要计算月份日期对象的第一天和最后一天的 。这些日期将用于$match管道中,以过滤掉当前不在当前月份的文档。

下一个管道流是由expenseCategoryId键这组收到的文件,这样你可以计算使用 累加器操作$sum当月花费的总$group阶段。

下面的代码实现上述:

appRouter.route('/expensecatgories').get(function(req, res){ 
    var today = new Date(), y = today.getFullYear(), m = today.getMonth(); 
    var firstDay = new Date(y, m, 1); 
    var lastDay = new Date(y, m + 1, 0); 
    var pipeline = [ 
     { 
      "$match": { 
       "date": { "$gte": firstDay, "$lt": lastDay } 
      } 
     }, 
     { 
      "$group": { 
       "_id": "$expenseCategoryId", 
       "totalSpentInThisMonth": { "$sum": "$amount" } 
      } 
     } 
    ]; 

    Expense.aggregate(pipeline, function (err, result){  
     if (err) throw err; 
     var categories = result.map(function(doc) { return new ExpenseCategory(doc) }); 
     Expense.populate(categories, { "path": "expenseCategoryId" }, function(err, results) { 
      if (err) throw err; 
      console.log(JSON.stringify(results, undefined, 4)); 
      res.json(results); 
     }); 
    });   
});