2016-08-30 135 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的數據返回給我。 –