在mongodb中内部匹配字段

在mongodb中内部匹配字段,mongodb,mongodb-query,Mongodb,Mongodb Query,我在mongodb中有以下文档 { "_id" : ObjectId("517b88decd483543a8bdd95b"), "studentId" : 23, "students" : [ { "id" : 23, "class" : "a" }, { "id" : 55, "class"

我在mongodb中有以下文档

    {
        "_id" : ObjectId("517b88decd483543a8bdd95b"),
        "studentId" : 23,
        "students" : [
          {
           "id" : 23,
           "class" : "a"
           },
          {
           "id" : 55,
           "class" : "b"
           }
        ]
     }
     {
        "_id" : ObjectId("517b9d05254e385a07fc4e71"),
        "studentId" : 55,
        "students" : [
           {
            "id" : 33,
            "class" : "c"
          }
         ]
     }
注意:不是实际数据,但模式完全相同

要求:使用单个查询在students数组中查找与studentId和students.idid匹配的文档

我试过下面的代码

db.data.aggregate({$match:{"students.id":"$studentId"}},{$group:{_id:"$student"}});
结果:空数组,如果我将{students.id:$studentId}替换为{students.id:33},它将返回上面显示的json中的第二个文档


是否可以使用单个查询获取此场景的文档?

db.data.find{students:{$elemMatch:{id:23}},studentId:23}

不幸的是,这是不可能的

要解决此问题,必须使用$where语句 示例:


但是$where不能与聚合框架一起使用

如果可能的话,我建议您在存储数据时设置条件,以便您可以在InstudentsList中进行快速真相检查。进行这种类型的查询会非常快

否则,使用聚合框架管道在单个查询中执行所需操作的方法相对复杂:

db.students.aggregate( 
    {$project: 
        {studentId: 1, studentIdComp: "$students.id"}},  
    {$unwind: "$studentIdComp"}, 
    {$project : { studentId : 1, 
        isStudentEqual: { $eq : [ "$studentId", "$studentIdComp" ] }}}, 
    {$match: {isStudentEqual: true}})
根据您的输入示例,输出为:

{
    "result" : [
         {
             "_id" : ObjectId("517b88decd483543a8bdd95b"),
             "studentId" : 23,
             "isStudentEqual" : true
         }
    ],
    "ok" : 1
}
步骤的简要说明:

用studentId构建文档的投影,并用一个数组构建一个新字段,数组中只包含id,这样它将包含第一个文档[23,55]。 使用该结构。为studenticomp数组中的每个数组元素创建一个新的临时文档。 现在,获取这些文档,并创建一个新的文档投影,该投影继续包含studentId,并添加一个名为isStudentEqual的新字段,该字段比较studentId和StudentdComp两个字段的相等性。请记住,此时只有一个临时文档包含这两个字段。 最后,检查比较值isStudentEqual是否为真,并返回将包含原始文档id和studentId的文档。 如果该学生多次出现在列表中,您可能需要在studentId或_id上对结果进行分组,以防止重复,但我不知道您是否需要这样做。
我认为问题在于如何找到条件为真的所有文档选择学生列表中包含studentId的文档。注意,$where对于聚合框架不是必需的,尽管WiredPairie的回答表明,您可以使用$project创建新字段,然后使用$MATCHEXPLICE@AsyaKamsky,但在许多问题中,我观察经典情况:比较某个层次中的一个字段和另一个字段。我知道,这个问题通常出现在一个糟糕的数据模型中。许多开发人员创建数据存储模型只是直接从关系存储中复制+粘贴;好的,公平地说,有时候需求会不断发展,随着需求的发展模式也会不断发展,这意味着首先要理解新的需求。这种解决方法可以作为理解长期需要添加到模式中的内容的中间步骤。