Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB:如何确定数组字段是否包含元素?_Mongodb - Fatal编程技术网

MongoDB:如何确定数组字段是否包含元素?

MongoDB:如何确定数组字段是否包含元素?,mongodb,Mongodb,我有两个收藏。第一个集合包含学生: { "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" } { "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" } { "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" } { "_id" : ObjectId("51780f796ec405

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

{ "_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
数组,其中包含注册课程的学生列表。当学生在网页上查看课程时,他需要查看是否已注册该课程。为此,当代表学生查询
课程
集合时,我们需要确定
学生
数组是否已经包含学生的ObjectId。是否有一种方法可以在find查询的投影中指定仅当存在时才从
students
数组中检索student
ObjectId

我试图看看是否可以使用$elemMatch操作符,但它面向一系列子文档。我知道我可以使用聚合框架,但在这种情况下,它似乎有点过头了。聚合框架可能不会像单个查找查询那么快。是否有一种方法可以查询课程集合,以便返回的文档的形式与此类似

{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
        "name" : "CS 101",
        "students" : [
                ObjectId("51780f796ec4051a536015d0"),
        ]
}
看来接线员能很好地为你服务

您可以这样做(伪查询):


或者,您可以删除
“course”:courseId
子句,并取回该学生注册的所有课程的集合。

[基于此,现在可以在最新版本中进行编辑]

[更新的答案]只有在已经注册的情况下,您可以通过以下方式查询以获取班级名称和学生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"
        }
    ]
}

我试图通过问题陈述和解决方案来解释。我希望这会有所帮助

问题陈述:

查找所有已发布的产品,其名称如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
                    )
                );
    

    这种方法的问题是,只有学生注册了课程,它才会返回课程集合中的文档。如果学生尚未注册,则需要进行第二次查询。这是无效的。第二个查询是检索学生的对象id吗?但这不是已经知道了吗(毕竟,您正在使用它进行第一次查询)。最终目标是检索课程文档,并有一个标志指示学生是否已注册。您提供的查询将仅在学生已注册的情况下检索课程文档。如果学生没有注册课程,则需要另一个查询来检索课程文档。我认为数据模型没有任何问题。我怀疑没有两个问题就没有真正的方法来实现你想要的,因为在一天结束时,你会问你的数据库两个问题:给我课程文档,学生是否参加了课程。即使在传统的关系数据库中,您也会面临同样的问题。延迟响应(抱歉!),但这从来不是Mongo的目标。Mongo用于存储非关系、无模式的数据对象。好吧,它没有试图减少所需的查询数量。感谢您确认我关于不能查询简单数组以及子文档数组的想法。我想我必须重新评估我的模式。你知道10Gen是否计划解决这个问题吗?我在Jira.mongodb.org上找不到这个问题的Jira票证,没有票证的情况下,任何东西都不会被安排发布,所以我想说肯定不会很快。使用$all中描述的$all是查询的操作员-查询不是问题,这个问题又回来了,所以我们讨论的是投影操作符。在
    课程
    集合中同时存储名称和对象id的问题是,学生名称存储在多个位置,这可能会失去同步。在这种情况下,查询将返回不完整的数据。如果服务器负载和硬件不是很紧,那么最好使用额外的查询来获取名称。您仍然可以将student
    ObjectId
    s存储为object以允许OP的查询:
    {“id”:…}
    $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
                    )
                );