Gebruik met MongoDB 3.4.4 het aggregatieraamwerk om het document te doorzoeken. Dit wordt mogelijk gemaakt met de $objectToArray
operator waarmee u de sleutels in het verwerkte veld kunt toewijzen aan een reeks sleutel/waarde-paren. De lijst zal gemakkelijk te filteren zijn en de sleutel(s) krijgen die overeenkomen met welke voorwaarde je ook hebt.
In het volgende voorbeeld bestaat de aggregatiepijplijn uit een extra veld dat de sleutel(s) bevat die voldoen aan de bovenstaande voorwaarde van een valse waarde, dus idealiter is het een array:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
wat oplevert
{
"_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"
]
}
Uitleg
Beginnend met de geneste uitdrukking
{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
de invoer naar $filter
operator { "$objectToArray": "$processed" }
converteert de sleutels in de processed
sleutel tot deze array:
[
{
"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
}
]
en $filter
zal de bovenstaande array filteren om alleen de objectelementen te hebben waarvan v
eigenschap is NOT
true
:
[
{
"k" : "original",
"v" : false
}
]
$map
zal dan een toegewezen array retourneren met alleen de waarden
[ { "k" : "original", "v" : false } ] => [ "original" ]
dus je eindigt met slechts
[ "original" ]
als resultaat.
Met oudere MongoDB-versies wordt het behoorlijk moeilijk om query's uit te voeren op dynamische sleutels. Overweeg om uw schema aan te passen om dit documentmodel te volgen dat gemakkelijker te doorzoeken is:
// 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 }
]
}
Uw zoekopdracht is eenvoudig
db.collection.find({"processed.value": false});
of gebruik $map
en $filter
om de sleutels terug te geven met false
waarden als
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])