我有两个系列。第一个集合包含学生:
{ "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" }
{ "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" }
{ "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" }
{ "_id" : ObjectId("51780f796ec4051a536015d2"), "name" : "Joe" }
第二个集合包含课程:
{
"_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
"name" : "CS 101",
"students" : [
ObjectId("51780f796ec4051a536015cf"),
ObjectId("51780f796ec4051a536015d0"),
ObjectId("51780f796ec4051a536015d2")
]
}
{
"_id" : ObjectId("51780fb5c9c41825e3e21fc5"),
"name" : "Literature",
"students" : [
ObjectId("51780f796ec4051a536015d0"),
ObjectId("51780f796ec4051a536015d0"),
ObjectId("51780f796ec4051a536015d2")
]
}
{
"_id" : ObjectId("51780fb5c9c41825e3e21fc6"),
"name" : "Physics",
"students" : [
ObjectId("51780f796ec4051a536015cf"),
ObjectId("51780f796ec4051a536015d0")
]
}
每个课程文档都包含 students
数组,其中包含已注册课程的学生列表。当学生在网页上查看课程时,他需要查看他是否已经注册了该课程。为此,当代表学生查询 courses
集合时,我们需要确定 students
数组是否已包含学生的 ObjectId。有没有办法在查找查询的投影中指定仅在存在时才从 students
数组中检索学生 ObjectId
?
我试图看看我是否可以使用 $elemMatch 运算符,但它适用于一系列子文档。我知道我可以使用聚合框架,但在这种情况下似乎有点过分了。聚合框架可能不会像单个查找查询那样快。有没有办法查询课程集合,以便返回的文档可以采用与此类似的形式?
{
"_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
"name" : "CS 101",
"students" : [
ObjectId("51780f796ec4051a536015d0"),
]
}
[基于此的编辑现在可以在最近的版本中]
【更新答案】只有在已经注册的情况下,您可以通过以下方式获取班级名称和学生ID。
db.student.find({},
{_id:0, name:1, students:{$elemMatch:{$eq:ObjectId("51780f796ec4051a536015cf")}}})
你会得到你所期望的:
{ "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015cf") ] }
{ "name" : "Literature" }
{ "name" : "Physics", "students" : [ ObjectId("51780f796ec4051a536015cf") ] }
[原答案] 目前无法做你想做的事。这是不幸的,因为如果学生作为对象存储在数组中,您将能够做到这一点。事实上,我对您只使用 ObjectId() 感到有点惊讶,因为如果您想显示参加特定课程的学生列表,您总是需要查找学生(首先查找 Id 的列表,然后再查找)在学生集合中查找名称 - 两个查询而不是一个!)
如果您在课程数组中存储(作为示例)一个 ID 和名称,如下所示:
{
"_id" : ObjectId("51780fb5c9c41825e3e21fc6"),
"name" : "Physics",
"students" : [
{id: ObjectId("51780f796ec4051a536015cf"), name: "John"},
{id: ObjectId("51780f796ec4051a536015d0"), name: "Sam"}
]
}
您的查询将只是:
db.course.find( { },
{ students :
{ $elemMatch :
{ id : ObjectId("51780f796ec4051a536015d0"),
name : "Sam"
}
}
}
);
如果那个学生只注册了 CS 101,你会回来:
{ "name" : "Literature" }
{ "name" : "Physics" }
{
"name" : "CS 101",
"students" : [
{
"id" : ObjectId("51780f796ec4051a536015cf"),
"name" : "John"
}
]
}
看起来 $in
运算符可以很好地满足您的目的。
你可以做这样的事情(伪查询):
if (db.courses.find({"students" : {"$in" : [studentId]}, "course" : courseId }).count() > 0) {
// student is enrolled in class
}
或者,您可以删除 "course" : courseId
子句并取回学生注册的所有课程的集合。
我试图通过提出问题陈述和解决方案来解释。我希望它会有所帮助
问题陈述:
查找所有已发布的产品,名称为 ABC 产品或 PQR 产品,价格应小于 15/-
解决方案:
以下是需要注意的条件
产品价格应小于 15 产品名称应为 ABC 产品或 PQR 产品 产品应处于已发布状态。
下面是应用上述标准来创建查询和获取数据的语句。
$elements = $collection->find(
Array(
[price] => Array( [$lt] => 15 ),
[$or] => Array(
[0]=>Array(
[product_name]=>Array(
[$in]=>Array(
[0] => ABC Product,
[1]=> PQR Product
)
)
)
),
[state]=>Published
)
);
不定期副业成功案例分享
course
集合中的问题在于,您会将学生姓名存储在多个位置,这可能会导致不同步。在这种情况下,您的查询将返回不完整的数据。如果服务器负载和硬件不是很薄,那么获取名称的额外查询可能更可取。您仍然可以将学生ObjectId
存储为对象以允许 OP 的查询:{"id":...}