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

标签 mongodb

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

{ "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" }
{ "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" }
{ "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" }
{ "_id" : ObjectId("51780f796ec4051a536015d2"), "name" : "Joe" }

第二个集合包含类(class):

{
        "_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")
        ]
}

每个类(class)文档都包含 students 数组,其中包含已注册类(class)的学生列表。当学生在网页上查看类(class)时,他需要查看他是否已经注册了该类(class)。为此,当代表学生查询 courses 集合时,我们需要确定 students 数组是否已经包含学生的 ObjectId。有没有办法在查找查询的投影中指定仅在 students 数组中检索学生 ObjectId 时才存在?

我试图查看是否可以使用 $elemMatch 运算符,但它适用于一组子文档。我知道我可以使用聚合框架,但在这种情况下似乎有点过分了。聚合框架可能不会像单个查找查询那样快。有没有办法查询类(class)集合,以便返回的文档可以是类似的形式?

{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
        "name" : "CS 101",
        "students" : [
                ObjectId("51780f796ec4051a536015d0"),
        ]
}

最佳答案

[编辑基于这一点现在可以在最近的版本中]

【更新答案】只有已经注册的同学,可以通过以下方式查询取回类(class)名称和学号。

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() 感到有点惊讶,因为如果您想显示参加特定类(class)的学生列表(查看查找 ID 的第一个列表,然后在学生集合中查找名称 - 两个查询而不是一个!)

如果您在类(class)数组中存储(例如)一个 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"
        }
    ]
}

关于MongoDB:如何找出数组字段是否包含元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16198429/

相关文章:

c# - 更新 MongoDB 中的嵌入式文档详细信息

node.js - 如何在nodejs中使用foreach进行Mongodb操作

mongodb - 按相对数组元素位置查找文档

node.js - 在Mongoose中填充后查询

javascript - Mongodb $unset 留下空数组对象(javascript)

mongodb - 如何同时使用 $gt 和 $lte 优化 MongoDB 查询?

linux - 如何在 Centos 7 上为 mongodb 禁用 THP

javascript - 通过 RESTful JSON 接口(interface)为 MongoDB 创建 API 的最快方法是什么?

Node.js 或使用 mongodb 服务器

java - Spring data MongoDB 检查字段是否包含文本