MongoDB:如何找出一个数组字段是否包含一个元素?

我有两个集合。 第一个集合包含学生:

{ "_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。 有没有一种方法来指定一个查询查询的投影来检索student数组的学生ObjectId只有当它在那里?

我试图看看是否可以使用elemMatch操作符,但是它是面向一系列子文档的。 我明白,我可以使用聚合框架,但在这种情况下,似乎是在矫枉过正。 聚合框架可能不会像单个查找查询那么快。 有没有办法查询课程收集,以便返回的文档可以在一个类似的forms?

 { "_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子句并获取一组学生注册的所有课程。