MongoDB takto zpracovává základní projekci s prvky pole. Zatímco můžete udělat něco takového:
Model.findOne({}, { "comments.upvotes": 1 },function(err,doc) {
})
A to by jen vrátilo pole "upvotes" z dílčích dokumentů pole komentářů pro všechny dokumenty odpovídající podmínce a všechny prvky pole, samozřejmě, nemůžete to kombinovat s vybranou polohovou projekcí pomocí poziční $
operátor. To v podstatě vyplývá z "teorie" to obecně vlastně chcete vrátit celé pole. Takže takhle to vždy fungovalo a není pravděpodobné, že se to brzy změní.
Abyste získali to, co chcete, potřebujete rozšířené možnosti pro manipulaci s dokumenty, které nabízí rámec agregace . To vám dává větší kontrolu nad tím, jak jsou dokumenty vráceny:
Model.aggregate(
[
// Match the document containing the array element
{ "$match": { "comments._id" : oid } },
// Unwind to "de-normalize" the array content
{ "$unwind": "$comments" },
// Match the specific array element
{ "$match": { "comments._id" : oid } },
// Group back and just return the "upvotes" field
{ "$group": {
"_id": "$_id",
"comments": { "$push": { "upvotes": "$comments.upvotes" } }
}}
],
function(err,docs) {
}
);
Nebo v moderních verzích MongoDB od 2.6 můžete dokonce udělat toto:
Model.aggregate(
[
{ "$match": { "comments._id" : oid } },
{ "$project": {
"comments": {
"$setDifference": [
{ "$map": {
"input": "$comments",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el._id", oid ] },
{ "upvotes": "$$el.upvotes" },
false
]
}
}},
[false]
]
}}
}}
],
function(err,docs) {
}
)
A to používá $map
a $setDifference
operátory, aby provedli „in-line“ filtrování obsahu pole bez předchozího zpracování $unwind
fázi.
Pokud tedy chcete větší kontrolu nad tím, jak se dokument vrací, pak agregační rámec je způsob, jak toho dosáhnout při práci s vloženými dokumenty.