Tak, można to zrobić na dwa sposoby. Możesz więc użyć $elemMatch
po stronie projekcji, jak już masz, z niewielkimi zmianami:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
Lub po prostu dodaj do części zapytania i użyj pozycyjnego $
operator:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
Tak czy inaczej jest całkowicie uzasadnione.
Jeśli chcesz czegoś bardziej zaangażowanego, możesz użyć .aggregate()
i jest to $project
operator zamiast:
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) {
Tak więc framework agregacji może być używany do znacznie więcej niż tylko agregowania wyników. To jest $project
operator zapewnia większą elastyczność niż jest dostępna w przypadku projekcji przy użyciu .find()
. Pozwala także na filtrowanie i zwracanie wyników wielu tablic, co jest również czymś, czego nie można zrobić za pomocą projekcji w .find()
.