Ya ada dua cara untuk melakukan ini. Jadi, Anda dapat menggunakan $elemMatch
di sisi proyeksi seperti yang sudah Anda miliki, dengan sedikit perubahan:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
Atau tambahkan saja ke bagian kueri dan gunakan $
position posisional operator:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
Cara mana pun benar-benar valid.
Jika Anda menginginkan sesuatu yang sedikit lebih terlibat dari itu, Anda dapat menggunakan .aggregate()
metode dan $project
sebagai gantinya:
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) {
Jadi kerangka kerja agregasi dapat digunakan untuk lebih dari sekadar menggabungkan hasil. Ini $project
operator memberi Anda lebih banyak fleksibilitas daripada yang tersedia untuk proyeksi menggunakan .find()
. Ini juga memungkinkan Anda untuk memfilter dan mengembalikan beberapa hasil larik, yang juga merupakan sesuatu yang tidak dapat dilakukan dengan proyeksi di .find()
.