说我有一个学生对象数组字段,例如[{id:foo, name: bar, imageurl:baz}]
在课程集合中。我想返回 在学生字段中具有给定学生ID的课程。
如果我使用$elemMatch
,我将在课程集合以及我想要的课程中获得很多文档。有没有办法解决这个问题,或者我绝对必须进行一些查询过滤才能返回一个文档?
编辑:示例课程集合:
{
_id: 1,
course: "OOP 101",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 2,
course: "Programming 101",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 3,
course: "Database 101",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
如果我使用$elemMatch
查找课程,则预期输出Jeff正在参加:
{
_id: 3,
course: "Database 101",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
vers
{
_id: 1,
course: "OOP 101"
{
_id: 2,
course: "Programming 101"
}
{
_id: 3,
course: "Database 101",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
我只想返回学生字段中具有给定学生ID的课程
您可以在查询中使用$elemMatch
根据嵌入式文档中字段的值选择文档。然后使用简单的投影,您可以返回感兴趣的字段:
> db.test.courses.find(
{students: {$elemMatch : { name: "john"}}}, // find all courses having
// "john" as a student
{course:1}) // keep only the course name
// and the _id
{ "_id" : 2, "course" : "Programming 101" }
{ "_id" : 3, "course" : "Database 101" }
当然,如果您需要整个文档,请勿指定任何投影:
> db.test.courses.find( {students: {$elemMatch : { name: "jeff"}}}).pretty()
{
"_id" : 3,
"course" : "Database 101",
"students" : [
{
"name" : "john",
"school" : 102,
"age" : 10
},
{
"name" : "jess",
"school" : 102,
"age" : 11
},
{
"name" : "jeff",
"school" : 108,
"age" : 15
}
]
}
请注意,这将返回所有课程,其中有一个具有匹配名称的学生。在我们的示例数据中," jeff" 仅与一门课程相关联。但这将返回两个文档," John" 。
如果您只想要其中一个,则可以将聚合框架与$limit
阶段一起使用(在大多数情况下,您应该在$limit
之前使用$sort
阶段):
> db.test.courses.aggregate([
{$match:{students: {$elemMatch : { name: "john"}}}},
{$limit:1}
]).pretty()
{
"_id" : 2,
"course" : "Programming 101",
"students" : [
{
"name" : "john",
"school" : 102,
"age" : 10
},
{
"name" : "ajax",
"school" : 100,
"age" : 7
},
{
"name" : "achilles",
"school" : 100,
"age" : 8
}
]
}