Ja, der er to måder at gøre dette på. Så du kan enten bruge $elemMatch
på projektionssiden, som du allerede har, med små ændringer:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
Eller bare føj til forespørgselsdelen og brug den positionelle $
operatør:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
Enten måde er fuldkommen gyldig.
Hvis du ville have noget lidt mere involveret end det, kan du bruge .aggregate()
metode, og det er $project
operatør i stedet:
Model.aggregate([
// Still match the document
{ "$match": "_id": id, "comments.created.by": "Jane" },
// Unwind the array
{ "$unwind": "$comments" },
// Only match elements, there can be more than 1
{ "$match": "_id": id, "comments.created.by": "Jane" },
// Project only what you want
{ "$project": {
"comments": {
"body": "$comments.body",
"by": "$comments.created.by"
}
}},
// Group back each document with the array if you want to
{ "$group": {
"_id": "$_id",
"comments": { "$push": "$comments" }
}}
],
function(err,result) {
Så aggregeringsrammen kan bruges til meget mere end blot at aggregere resultater. Det er $project
operator giver dig mere fleksibilitet, end der er tilgængelig for projektion ved hjælp af .find()
. Det giver dig også mulighed for at filtrere og returnere flere array-resultater, hvilket også er noget, der ikke kan gøres med projektion i .find()
.