Ja, es gibt zwei Möglichkeiten, dies zu tun. Sie können also entweder den $elemMatch
auf der Projektionsseite, wie Sie es bereits haben, mit geringfügigen Änderungen:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
Oder fügen Sie einfach den Abfrageteil hinzu und verwenden Sie den Positionscode $
Betreiber:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
So oder so ist vollkommen gültig.
Wenn Sie etwas komplizierteres möchten, können Sie den .aggregate()
-Methode und es ist $project
Operator stattdessen:
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) {
Das Aggregations-Framework kann also für viel mehr als nur das Aggregieren von Ergebnissen verwendet werden. Es ist $project
-Operator gibt Ihnen mehr Flexibilität als die Projektion mit .find()
. Außerdem können Sie mehrere Array-Ergebnisse filtern und zurückgeben, was mit der Projektion in .find()
ebenfalls nicht möglich ist .