我在mongoDB中有一个深度嵌套的文档,我想获取单个子对象。
示例:
{
"schoolName": "Cool School",
"principal": "Joe Banks",
"rooms": [
{
"number": 100
"teacher": "Alvin Melvin"
"students": [
{
"name": "Bort"
"currentGrade": "A"
},
// ... many more students
]
},
// ... many more rooms
]
}
最近Mongo更新为允许使用$elemMatch projection进行1级深度子对象检索:
var projection = { _id: 0, rooms: { $elemMatch: { number: 100 } } };
db.schools.find({"schoolName": "Cool School"}, projection);
// returns { "rooms": [ /* array containing only the matching room */ ] }
但是当我尝试以同样的方式取一个学生(2级深)时,我收到一个错误:
var projection = { _id: 0, "rooms.students": { $elemMatch: { name: "Bort" } } };
db.schools.find({"schoolName": "Cool School"}, projection);
// "$err": "Cannot use $elemMatch projection on a nested field (currently unsupported).", "code": 16344
有没有办法在mongoDB文档中检索任意深度的子对象?
我正在使用Mongo 2.2.1
答案 0 :(得分:3)
我最近问了一个类似的问题,可以提供一个适当的一般性答案(见Using MongoDB's positional operator $ in a deeply nested document query)
此解决方案仅支持Mongo 2.6+,但从那时起您可以使用聚合框架的$ redact函数。
这是一个示例查询,应该只返回您的学生Bort。
db.users.aggregate({
$match: { schoolName: 'Cool School' }
}, {
$project: {
_id: 0,
'schoolName': 1,
'rooms.number': 1,
'rooms.students': 1
}
}, {
$redact: {
$cond: {
"if": {
$or: [{
$gte: ['$schoolName', '']
}, {
$eq: ['$number', 100]
}]
},
"then": "$$DESCEND",
"else": {
$cond: {
"if": {
$eq: ['$name', 'Bort']
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}
}
}
});
$ redact可用于通过在匹配文档中递归匹配或修剪子文档来进行子查询。
You can read about $redact here要了解更多有关正在发生的事情,但我发现的设计模式有以下要求:
$eq: ['$number', 100]
匹配数字为100的房间$gte: ['$uniqueField': '']
答案 1 :(得分:0)
我目前没有mongodb 2.2方便,所以我无法测试这个,但你试过了吗?
var projection = { _id: 0, rooms: { $elemMatch: { "students.name": "Bort" } } };
db.schools.find({"schoolName": "Cool School"}, projection);