Dengan MongoDB 3.4.4, gunakan kerangka kerja agregasi untuk mengkueri dokumen. Ini dimungkinkan dengan $objectToArray
operator yang memungkinkan Anda untuk memetakan kunci di bidang yang diproses ke larik pasangan kunci/nilai. Daftar akan mudah difilter dan mendapatkan kunci yang cocok dengan kondisi apa pun yang Anda miliki.
Dalam contoh berikut, pipa agregasi terdiri dari bidang tambahan yang menyimpan kunci yang cocok dengan kondisi di atas yang memiliki nilai salah, jadi idealnya adalah array:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
yang menghasilkan
{
"_id" : ObjectId("5501b1648ef0b4eccc41814e"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
},
"notProcessed" : [
"original"
]
}
Penjelasan
Dimulai dengan ekspresi bersarang
{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
masukan ke $filter
operator { "$objectToArray": "$processed" }
akan mengonversi kunci dalam processed
kunci larik ini:
[
{
"k" : "320",
"v" : true
},
{
"k" : "480",
"v" : true
},
{
"k" : "540",
"v" : true
},
{
"k" : "720",
"v" : true
},
{
"k" : "800",
"v" : true
},
{
"k" : "1080",
"v" : true
},
{
"k" : "original",
"v" : false
},
{
"k" : "iPhone",
"v" : true
}
]
dan $filter
akan memfilter array di atas agar hanya memiliki elemen objek yang v
properti NOT
true
:
[
{
"k" : "original",
"v" : false
}
]
$map
kemudian akan mengembalikan array yang dipetakan hanya dengan nilai
[ { "k" : "original", "v" : false } ] => [ "original" ]
jadi Anda berakhir hanya dengan
[ "original" ]
sebagai hasilnya.
Dengan versi MongoDB yang lebih lama, akan sangat sulit untuk mengeluarkan kueri terhadap kunci dinamis. Pertimbangkan untuk memodifikasi skema Anda untuk mengikuti model dokumen ini yang lebih mudah untuk ditanyakan:
// this operation changes the schema
var processed = [];
db.collection.find().forEach( function(doc) {
for(key in doc.processed) {
if(doc.processed.hasOwnProperty(key)) {
var item = { key: key, value: doc.processed[key] }
processed.push(item);
}
}
doc.processed = processed;
db.collection.save(doc);
});
// modified schema
{
"link": "xxxxx.jpg"
"_id": ObjectId("5501b1648ef0b4eccc41814e"),
"processed": [
{ "key": "320", "value": true },
{ "key": "480", "value": true },
{ "key": "540", "value": true },
{ "key": "720", "value": true },
{ "key": "800", "value": true },
{ "key": "1080", "value": true },
{ "key": "original", "value": false },
{ "key": "iPhone", "value": true }
]
}
Permintaan pencarian Anda akan sederhana
db.collection.find({"processed.value": false});
atau gunakan $map
dan $filter
untuk mengembalikan kunci dengan false
nilai sebagai
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])