Да, има два начина да направите това. Така че можете да използвате или $elemMatchкод>
от страната на проекцията, както вече имате, с леки промени:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
Или просто добавете към частта на заявката и използвайте позиционния $
оператор:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
И двата начина са напълно валидни.
Ако искате нещо малко по-ангажирано от това, можете да използвате .aggregate()
метод и е $project
оператор вместо:
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) {
Така че рамката за агрегиране може да се използва за много повече от просто агрегиране на резултати. Това е $project
Операторът ви дава повече гъвкавост, отколкото е налична за проекция с помощта на .find()
. Освен това ви позволява да филтрирате и връщате множество резултати от масиви, което също е нещо, което не може да се направи с проекция в .find()
.