【问题标题】:Make $elemMatch (projection) return all objects that match criteria使 $elemMatch (projection) 返回所有符合条件的对象
【发布时间】:2020-06-12 11:49:11
【问题描述】:

我将使用here中的示例

{
 _id: 1,
 zipcode: 63109,
 students: [
              { name: "john", school: 102, age: 10 },
              { name: "jess", school: 102, age: 11 },
              { name: "jeff", school: 108, age: 15 }
           ]
}
{
 _id: 2,
 zipcode: 63110,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 3,
 zipcode: 63109,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 4,
 zipcode: 63109,
 students: [
              { name: "barney", school: 102, age: 7 },
           ]
}

如果我跑了

db.schools.find( { zipcode: 63109 },
             { students: { $elemMatch: { school: 102 } } } )

它将给出每个数组的first结果。命名:

{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }

如何让它返回符合条件的数组的所有对象(而不仅仅是第一个对象)?意思是:

{
 _id: 1,
 students: [
              { name: "john", school: 102, age: 10 },
              { name: "jess", school: 102, age: 11 }
           ]
}    
{ _id: 3 }
{_id: 4, students: [ { name: "barney", school: 102, age: 7 }]}

【问题讨论】:

  • 看起来文档说它的 $elemMatch 只返回第一个数组元素,所以我想你必须在 python 中做,或者用学生列表 + 邮政编码创建新表,如{ "name" : "john", "school" : 102, "age" : 10, zipcode: 63109 }跨度>

标签: mongodb pymongo


【解决方案1】:

为了返回多个子文档,您需要使用聚合框架。这将返回您要查找的所有子文档:

db.zip.aggregate(
  {$match: {zipcode: 63109}},
  {$unwind: "$students"},
  {$match: {"students.school": 102}}
)

你可以做各种事情来获得不同的输出,但这会返回:

{
    "result" : [
        {
            "_id" : 1,
            "zipcode" : 63109,
            "students" : {
                "name" : "john",
                "school" : 102,
                "age" : 10
            }
        },
        {
            "_id" : 1,
            "zipcode" : 63109,
            "students" : {
                "name" : "jess",
                "school" : 102,
                "age" : 11
            }
        },
        {
            "_id" : 4,
            "zipcode" : 63109,
            "students" : {
                "name" : "barney",
                "school" : 102,
                "age" : 7
            }
        }
    ],
    "ok" : 1
}

【讨论】:

  • 它返回空值。你能帮帮我吗
  • @UzumakiNaruto:您是否尝试将.zip 替换为您收藏的名称?例如,db.zip.aggregate 变为 db.yourcollection.aggregate
  • 即使我有相同的数据类型和对象,除了邮政编码部分。但是使用这个查询并不能解决我的目的。有人可以帮忙吗?
【解决方案2】:

以前和错误的答案:

这应该从今天开始工作。见https://docs.mongodb.com/v3.2/reference/operator/projection/positional/#array-field-limitations

在查询中使用$elemMatch 查询并在投影中公开子文档时,您应该得到正确的结果,如下所示:

db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } },
                 { 'students.$': 1 } )


新答案

目前无法使用find() 将子文档列表限制为与查询匹配的那些。请改用aggregate() 或采取以下一种可能:

您可以通过在投影中添加数组属性来获取匹配文档的所有子文档:

db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 }, { "name" : "jess", "school" : 102, "age" : 11 }, { "name" : "jeff", "school" : 108, "age" : 15 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }

或者您可以在子文档上获取与$elemMatch 查询匹配的第一项:

db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students.$': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }

【讨论】:

  • 因为您的投影示例根据文档返回第一个匹配项,而不是所有问题。
  • 尝试了几次并将答案更新为有效的答案:) @alf 不是直接要求的,但可能对其他人有帮助。
【解决方案3】:

在类似过滤的情况下,这对我有用。现在我知道这个问题是多年前提出的,但对于像我这样寻求答案的人来说。这对我有用。感谢原始答案!

在这个特定问题的情况下: outerparamzipcodeinnerarray.propertystudents.school

let cursor = db
    .collection("somecollection")
    .aggregate(
      { $match: { outerparam: outermatch } },
      { $unwind: "$innerarray" },
      { $match: { "innerarray.property": propertymatch } },
      { $project: { "innerarray.$": 1 } });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-25
    • 2014-10-29
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    相关资源
    最近更新 更多