MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongo - Übereinstimmung, bei der der Objektschlüssel variabel ist

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

zurück
[ { "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"
            }
        }
    } }
])