Fold All / Expand All

2014年9月6日 星期六

[MongoDB] 只顯示在陣列中符合條件的 subdocument

標題怪怪的

想要做的事是,在陣列裡是 document,用 find() 找到符合的 document,預設會把整個陣列都傳回來,不論條件是否符合

假設 collection students 有以下的 document
```
{ "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 },
                                       { grade: 85, mean: 90, std: 5 },
                                       { grade: 90, mean: 85, std: 3 } ] }

{ "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 },
                                       { grade: 78, mean: 90, std: 5 },
                                       { grade: 88, mean: 85, std: 3 } ] }
```

這時候下找出 mean 大於 85 的
```
db.students.find(
    {'grades.mean': { $gt: 85}},
    {'grades': 1}
)
```

grades 的內容都會出現,不論 mean 是否大於 85

MongoDB 有個 projection operator $,可以限制只顯示符合的第1個
http://docs.mongodb.org/manual/reference/operator/projection/positional/#project-array-documents

改成
```
db.students.find(
    {'grades.mean': { $gt: 85}},
    {'grades.$': 1}
)
```

grades 就只會出現符合的第1個

但是問題來啦,像是第2個 document 裡,符合大於85條件的有2個,用 $ 的話,只會列出1個,要列出所有符合的,要如何下呢?

用 aggregate() ,先 $unwind 拆掉 array,再 $group 回來
```
db.students.aggregate([{
    $unwind: '$grades'
}, {
    $match: {
        'grades.mean': {
            $gt: 85
        }
    }
}, {
    $group: {
        _id: '$_id',
        grades: {
            $push: '$grades'
        }
    }
}])
```

不過目前要用的 array 是在 nested document 裡面,似乎還不支援…

沒有留言: