Apa yang Anda cari adalah posisi $
operator dan "proyeksi". Untuk satu bidang Anda harus mencocokkan elemen larik yang diperlukan menggunakan "notasi titik", untuk lebih dari satu bidang gunakan $elemMatch
:
db.products.find(
{ "items.date": "31.08.2014" },
{ "shop": 1, "name":1, "items.$": 1 }
)
Atau $elemMatch
untuk lebih dari satu bidang yang cocok:
db.products.find(
{ "items": {
"$elemMatch": { "date": "31.08.2014", "purchasePrice": 1 }
}},
{ "shop": 1, "name":1, "items.$": 1 }
)
Ini hanya berfungsi untuk elemen array tunggal dan hanya satu yang akan dikembalikan. Jika Anda ingin lebih dari satu elemen larik dikembalikan dari kondisi Anda, maka Anda memerlukan penanganan lebih lanjut dengan kerangka kerja agregasi.
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$unwind": "$items" },
{ "$match": { "items.date": "31.08.2014" } },
{ "$group": {
"_id": "$_id",
"shop": { "$first": "$shop" },
"name": { "$first": "$name" },
"items": { "$push": "$items" }
}}
])
Atau mungkin dalam bentuk yang lebih pendek/lebih cepat sejak MongoDB 2.6 di mana array item Anda berisi entri unik:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$project": {
"shop": 1,
"name": 1,
"items": {
"$setDifference": [
{ "$map": {
"input": "$items",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.date", "31.08.2014" ] },
"$$el",
false
]
}
}},
[false]
]
}
}}
])
Atau mungkin dengan $redact
, tapi sedikit dibuat-buat:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
Lebih modern, Anda akan menggunakan $filter
:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$addFields": {
"items": {
"input": "$items",
"cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
}
}}
])
Dan dengan beberapa kondisi, $elemMatch
dan $and
dalam $filter
:
db.products.aggregate([
{ "$match": {
"$elemMatch": { "date": "31.08.2014", "purchasePrice": 1 }
}},
{ "$addFields": {
"items": {
"input": "$items",
"cond": {
"$and": [
{ "$eq": [ "$$this.date", "31.08.2014" ] },
{ "$eq": [ "$$this.purchasePrice", 1 ] }
]
}
}
}}
])
Jadi itu hanya tergantung pada apakah Anda selalu mengharapkan satu elemen cocok atau beberapa elemen, dan kemudian pendekatan mana yang lebih baik. Tetapi jika memungkinkan .find()
metode umumnya akan lebih cepat karena tidak memiliki overhead dari operasi lain, yang pada formulir terakhir tidak tertinggal jauh di belakang sama sekali.
Sebagai catatan tambahan, "tanggal" Anda direpresentasikan sebagai string yang bukan ide yang bagus untuk kedepannya. Pertimbangkan untuk mengubahnya menjadi Tanggal yang tepat jenis objek, yang akan sangat membantu Anda di masa mendatang.