Con MongoDB 3.4.4, use el marco de agregación para consultar el documento. Esto es posible con $objectToArray
operador que le permite asignar las claves en el campo procesado a una matriz de pares clave/valor. La lista será fácil de filtrar y obtener las claves que coincidan con cualquier condición que tenga.
En el siguiente ejemplo, la canalización de agregación consta de un campo adicional que contiene la(s) clave(s) que coinciden con la condición anterior de tener un valor falso, por lo que idealmente será una matriz:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
que produce
{
"_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"
]
}
Explicaciones
Comenzando con la expresión anidada
{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
la entrada a $filter
operator { "$objectToArray": "$processed" }
convertirá las claves en el processed
clave para esta matriz:
[
{
"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
}
]
y $filter
filtrará la matriz anterior para tener solo los elementos de objeto cuyo v
la propiedad es NOT
true
:
[
{
"k" : "original",
"v" : false
}
]
$map
luego devolverá una matriz asignada con solo los valores
[ { "k" : "original", "v" : false } ] => [ "original" ]
entonces terminas con solo
[ "original" ]
como resultado.
Con versiones anteriores de MongoDB, será bastante difícil emitir consultas contra claves dinámicas. Considere modificar su esquema para seguir este modelo de documento que es más fácil de consultar:
// 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 }
]
}
Su consulta de búsqueda será simplemente
db.collection.find({"processed.value": false});
o use $map
y $filter
para devolver las claves con false
valores como
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])