Return only specific fields from projection array

2019-03-15 18:50发布

问题:

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:

  • I am not trying to perform a $slice from mongodb aggregation framework - Fetch first document's field of the nested array.

  • Nor am I trying to flatten the sub-document from Return only array value in mongo projection because I still want some fields from the top document.

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?

回答1:

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