2016-08-30 131 views
2

上午有我节点应用以下猫鼬架构使用猫鼬

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

有人可以帮助我?

回答

0

可以使用positional $ operatorprojection在你的结果返回匹配的费用数组元素:

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

或多个匹配,你可以使用聚合框架的$filter运营商在$project管道如:

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

或者如果您使用的是旧版本o不具备对MongoDB的3.2 $filter支持度f猫鼬的驱动程序,你可以使用$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)); 
}); 
+0

这只返回正确的数据。但它只返回一个对象。我怎样才能获得同一个月的数组中的所有对象? –

+0

这将返回一个空对象 –

+0

我想我知道为什么,这是因为''match'的aggregate()'函数需要通过'_id'匹配,所以必须首先将值转换为ObjectId。检查我的更新版本。 – chridam

0

假设这可工作

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) 
         }) 
+0

由于我已经编写了所有的POST方法,如果可以有一个解决方案而不必更改Schema,那将是非常好的。你能提出一个具有相同模式的解决方案吗? –

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

这也没有运气。 –

+0

为什么? 'elemMatch'工作很好,应该是正确的。 – gianlucatursi

+0

它仍然以month == sept的数据返回给我。 –