2015-11-18 139 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); 
     }); 
    });   
});