Mongoose:从其他集合中填充集合中的字段

时间:2015-11-18 11:22:38

标签: mongodb mongoose

我有2个Mongoose集合:ExpenseCategory和Expense

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);

Node.js 中写了GET api次来回复所有ExpenseCategory items

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

在上面GET method中,我希望在返回之前在每个totalSpentInThisMonth项中填充字段expenseCategories。此字段需要计算为所有expense.amount的总和,其中expense.expenseCategoryIdexpenseCategory.idexpense.date在当月匹配。

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

1 个答案:

答案 0 :(得分:0)

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

下一个管道流将是 $group 阶段,它按expenseCategoryId键对传入文档进行分组,以便您可以使用以下内容计算当前月份的总支出 累加器运算符 $sum

以下代码实现了上述内容:

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);
        });
    });        
});