11

I'm looking at MongoDB's documentation on the $ and $elemMatch projections. I'm trying to figure out how to return only a subset of a projection array's fields, but I cannot seem to figure it out.

Related posts:

Say I have the following documents in the test collection:

{
    "_id": "A",
    "array": [
        {"key": 1, "name": "foo", "data": {}},
        {"key": 2, "name": "bar", "data": {}}
    ],
    "extra": {}
},
{
    "_id": "B",
    "array": [
        {"key": 3, "name": "spam", "data": {}},
        {"key": 4, "name": "eggs", "data": {}}
    ],
    "extra": {}
}

The query I effectively want to perform is:

db.test.findOne({"array.key": 1}, {"array.$.name": 1, "extra": 1})

Which I would expect it to only return name under the sub-document in the array where key was 1. E.g.,

{
    "_id": "A",
    "array": [
        {"name": "foo"}
    ],
    "extra": {}
}

But if I perform that query, I get this instead:

{
    "_id": "A",
    "array": [
        {"key": 1, "name": "foo", "data": {}}
    ],
    "extra": {}
}

Which is identical to doing the query:

db.test.findOne({"array.key": 1}, {"array.$": 1, "extra": 1})

I've also tried the following which results in the same:

db.test.findOne({"array.key": 1}, {"array.$": 1, "array.name": 1, "extra": 1})

Is there a way to only return a subset of the fields for array.$ instead of the whole sub-document?

Community
  • 1
  • 1
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144

1 Answers1

9

Are you specifically trying to do this without using aggregate?

db.test.aggregate([{$unwind:"$array"},
                   {$match:{"array.key":1}},
                   {$project:{"array.name":1, extra:1}}])
Ben Gamble
  • 411
  • 2
  • 3
  • I wasn't aware that aggregation could accomplish what I was trying to do because I'm not aggregating multiple documents. – Uyghur Lives Matter Apr 26 '14 at 23:17
  • 6
    But what if you can't use aggregates? I'm a little confused about this, given that you can use the $ operator and access a subfield in an update like this: `db.students.update( { _id: 4, "grades.grade": 85 }, { $set: { "grades.$.std" : 6 } } )` – Bilk Feb 04 '15 at 11:37