Make $elemMatch (projection) return all objects that match criteria

前端 未结 3 1228
死守一世寂寞
死守一世寂寞 2020-12-24 07:09

I will use the example from here

{
 _id: 1,
 zipcode: 63109,
 students: [
              { name: \"john\", school: 102, age: 10 },
              { name: \"je         


        
相关标签:
3条回答
  • 2020-12-24 08:12

    In order to return multiple subdocuments, you're going to need to use the aggregation framework. This will return all of the subdocuments you're looking for:

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

    You can do various things to get different output, but this will return:

    {
        "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
    }
    
    0 讨论(0)
  • 2020-12-24 08:13

    This worked for me in a case of similar filtering. Now I know this question was asked many years ago, but to anyone looking for an answer like me. here's what worked for me. Thanks to original answer!

    In the case of this particular question: outerparam is zipcode and innerarray.property is students.school.

    let cursor = db
        .collection("somecollection")
        .aggregate(
          { $match: { outerparam: outermatch } },
          { $unwind: "$innerarray" },
          { $match: { "innerarray.property": propertymatch } },
          { $project: { "innerarray.$": 1 } });
    
    0 讨论(0)
  • 2020-12-24 08:14

    Previous and incorrect answer:

    This should work as of today. See https://docs.mongodb.com/v3.2/reference/operator/projection/positional/#array-field-limitations

    You should get the correct result when querying using $elemMatch in the query and exposing the sub-document in the projection like following:

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


    New answer

    Limiting the list of sub-documents to those matching the query is as of now not possible using find(). Please take aggregate() instead or take one of the following possibilities:

    You could either get all the sub-documents of the matching document by adding the array-property in the projection:

    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 } ] }
    

    Or you can get the first item matching the $elemMatch query on the sub-documents:

    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 } ] }
    
    0 讨论(0)
提交回复
热议问题