使用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);
或者对于多个匹配,您可以在$project
pipe道中使用聚合框架的$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}); } });