2013-05-30 104 views
25

我剛剛陷入了這個問題。我有兩個貓鼬模式:貓鼬 - 通過條件查找子文檔

var childrenSchema = mongoose.Schema({ 
    name: { 
     type: String 
    }, 
    age: { 
     type: Number, 
     min: 0 
    } 
}); 

var parentSchema = mongoose.Schema({ 
    name : { 
     type: String 
    }, 
    children: [childrenSchema] 
}); 

問題是,如何來從每一位家長文檔的所有子文檔(在這種情況下,childrenSchema對象)?假設我有一些數據:

var parents = [ 
    { name: "John Smith", 
    children: [ 
     { name: "Peter", age: 2 }, { name: "Margaret", age: 20 } 
    ]}, 
    { name: "Another Smith", 
    children: [ 
     { name: "Martha", age: 10 }, { name: "John", age: 22 } 
    ]} 
]; 

我想檢索 - 在一個查詢中 - 所有18歲以上的孩子。可能嗎?每一個答案將不勝感激,謝謝!

+0

你希望它僅返回父母,如果孩子年滿18歲或你希望它只是填充的孩子,每個家長都超過18歲? –

+0

這將是偉大的,如果我得到一套「兒童」... –

回答

38

在最新的MongoDB版本中,您可以使用$elemMatch作爲查詢投影操作符。從蒙戈外殼:

db.parents.find(
    {'children.age': {$gte: 18}}, 
    {children:{$elemMatch:{age: {$gte: 18}}}}) 

此過濾年幼的孩子的文件出了children數組:

{ "_id" : ..., "children" : [ { "name" : "Margaret", "age" : 20 } ] } 
{ "_id" : ..., "children" : [ { "name" : "John", "age" : 22 } ] } 

正如你所看到的,孩子們還在父文件裏面分組。 MongoDB查詢從集合中返回文檔。您可以使用聚合框架的$unwind方法把它們分割成單獨的文件:

> db.parents.aggregate({ 
    $match: {'children.age': {$gte: 18}} 
}, { 
    $unwind: '$children' 
}, { 
    $match: {'children.age': {$gte: 18}} 
}, { 
    $project: { 
     name: '$children.name', 
     age:'$children.age' 
    } 
}) 
{ 
    "result" : [ 
     { 
      "_id" : ObjectId("51a7bf04dacca8ba98434eb5"), 
      "name" : "Margaret", 
      "age" : 20 
     }, 
     { 
      "_id" : ObjectId("51a7bf04dacca8ba98434eb6"), 
      "name" : "John", 
      "age" : 22 
     } 
    ], 
    "ok" : 1 
} 

我重複了性能$match條款:第一次通過它消除父母與沒有孩子年滿18歲,所以$unwind只考慮有用的文件。第二個$match刪除$unwind輸出不匹配,並且$project將兒童的信息從子文檔提升到頂層。

+0

謝謝,我會檢查:) –

+0

它的工作! :) 感謝幫助! :)我在哪裏可以獲得關於高級MongoDB操作的一些文檔?它的文檔夠了嗎?我希望儘可能多地學習MongoDB :) –

+1

以10gen的在線MongoDB For Developers類爲例,閱讀Rick Copeland的MongoDB Design Patterns一書。 –

16

在貓鼬,你也可以用優雅的.populate()功能是這樣的:

parents 
.find({}) 
.populate({ 
    path: 'children', 
    match: { age: { $gte: 18 }}, 
    select: 'name age -_id' 
}) 
.exec() 
+1

'populate'在引用其他集合中的文檔時起作用。 OP正在使用子文檔。 – Lulylulu

+0

這是一段很長的時間,因爲我做了這個答案:)我現在不能嘗試,但我認爲它也適用於嵌入式文檔! – AbdelHady