Verwenden Sie mit MongoDB 3.4.4 das Aggregationsframework, um das Dokument abzufragen. Dies wird durch $objectToArray
ermöglicht
-Operator, mit dem Sie die Schlüssel im verarbeiteten Feld einem Array von Schlüssel/Wert-Paaren zuordnen können. Die Liste lässt sich leicht filtern und Sie erhalten die Schlüssel, die Ihren Bedingungen entsprechen.
Im folgenden Beispiel besteht die Aggregationspipeline aus einem zusätzlichen Feld, das die Schlüssel enthält, die der obigen Bedingung entsprechen, einen falschen Wert zu haben, also ist es idealerweise ein Array:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
was ergibt
{
"_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"
]
}
Erklärungen
Beginnend mit dem verschachtelten Ausdruck
{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
die Eingabe für $filter
Operator { "$objectToArray": "$processed" }
konvertiert die Schlüssel in den processed
Schlüssel zu diesem 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
}
]
und $filter
filtert das obige Array so, dass es nur die Objektelemente enthält, deren v
Eigenschaft ist NOT
true
:
[
{
"k" : "original",
"v" : false
}
]
$map
gibt dann ein zugeordnetes Array mit nur den Werten
[ { "k" : "original", "v" : false } ] => [ "original" ]
so endet man mit nur
[ "original" ]
als Ergebnis.
Bei älteren MongoDB-Versionen wird es ziemlich schwierig sein, Abfragen für dynamische Schlüssel durchzuführen. Erwägen Sie, Ihr Schema so zu ändern, dass es diesem Dokumentenmodell folgt, das einfacher abzufragen ist:
// 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 }
]
}
Ihre Suchabfrage wird einfach sein
db.collection.find({"processed.value": false});
oder verwenden Sie $map
und $filter
um die Schlüssel mit false
zurückzugeben Werte als
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])