使用Mongoose在对象数组中使用模式

我的节点应用程序中有以下的Mongoose模式

var expenseSchema = new Schema({ particular : String, date : {type : Date, default: Date.now}, paid_by : String, amount : Number, month : String }); var roomSchema = new Schema({ name: String, admin: String, roomies : [String], expenses : [expenseSchema] },{ collection : 'rooms' }); 

我需要使用find()来获得特定月份的房间费用。 这是我正在尝试,但它返回给我的整个房间的对象

 Room.findOne({_id : req.params._id, 'expenses.month' : 'oct'}).exec(function(err, result){ if(result == null) { res.json({result : 'Oops! We couldn\'t find any rooms...'}); } else if(err) { res.json({result : 'Error in getting Rooms'}); } else { res.json({result : result}); } }); 

有人可以帮我弄这个吗?

您可以在投影中使用positional $ operator来返回结果中匹配的费用数组元素:

 Room.findOne( { "_id": req.params._id, "expenses.month": "oct" }, { "expenses.$": 1 } ).exec(callback); 

或者对于多个匹配,您可以在$projectpipe道中使用聚合框架的$filter操作符:

 var ObjectId = mongoose.Types.ObjectId; Room.aggregate() .match({ "_id": new ObjectId(req.params._id), "expenses.month": "oct" }) .project({ "expenses": { "$filter": { "input": "$expenses", "as": "item", "cond": { "$eq": [ "$$item.month", "oct" ] } } } }) .exec(callback); 

或者如果您使用的Mongoose驱动程序的旧版本不支持MongoDB 3.2 $filter ,则可以使用$map$setDifference ,您可以在这里过滤数组内容而不使用$unwind

 var ObjectId = mongoose.Types.ObjectId; Room.aggregate([ { "$match": { "_id": new ObjectId(req.params._id), "expenses.month": "oct" } }, { "$project": { "expenses": { "$setDifference": [ { "$map": { "input": "$expenses", "as": "items", "in": { "$cond": [ { "$eq": [ "$$items.month", "oct" ] }, "$$items", false ] } } }, [false] ] } } } ], function(err, results){ console.log(JSON.stringify(results[0], null, 4)); }); 

假设这可以工作

 var expenseSchema = new Schema({ particular : String, date : {type : Date, default: Date.now}, paid_by : String, amount : Number, month : String }); var roomSchema = new Schema({ name: String, admin: String, roomies : [String], expense_id : type: Schema.Types.ObjectId, ref: 'expenseSchema' },{ collection : 'rooms' }); Room.findOne({expense_id: req.params._id , "expenses.month": "oct" }) .populate('expense_id') .exec(function (err, doc) { if (err) { throw err } console.log(doc) }) 
 Room.findOne({ _id : req.params._id, 'expenses.month':'oct' },{ 'expenses': { $elemMatch:{ 'month':'oct' } } ).exec( function(err, result){ if(result == null) { res.json({result : 'Oops! We couldn\'t find any rooms...'}); } else if(err) { res.json({result : 'Error in getting Rooms'}); } else { res.json({result : result}); } });