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

Element basierend auf zwei Werten finden

Aus dem vorher verlinktes Dupe (möglich) , eine Lösung mit $where würde folgen:

db.collection.find({
    "$where": function() {
        self = this;
        return this.actors.filter(function(actor) {
            return self.director._id === actor._id;
        }).length > 0
    }
})

Und der andere vorgeschlagene Ansatz, der das Aggregationsframework verwendet $redact Leitung:

db.collection.aggregate([
    { 
        "$redact": { 
            "$cond": [
                { 
                    "$setIsSubset": [ 
                        ["$director._id"], 
                        {
                            "$map": {
                                "input": "$actors",
                                "as": "el",
                                "in": "$$el._id"
                            }
                        }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

Oben die Bedingungslogik für $redact erfolgt durch die Verwendung von Mengenoperatoren $setIsSubset und $map .

Der $map -Operator gibt ein Array mit nur den Akteur-IDs von actors zurück Array, nachdem ein Ausdruck auf jedes Element im Array angewendet wurde. Also zum Beispiel der Ausdruck

{
    "$map": {
        "input": "$actors",
        "as": "el",
        "in": "$$el._id"
    }
}

wenn auf das Actors-Array angewendet

[ 
    {
        "_id" : "artist:3",
        "first_name" : "James",
        "last_name" : "Stewart",
        "birth_date" : "1908",
        "role" : "John Ferguson"
    }, 
    {
        "_id" : "artist:16",
        "first_name" : "Kim",
        "last_name" : "Novak",
        "birth_date" : "1925",
        "role" : "Madeleine Elster"
    }, 
    {
        "_id" : "artist:282",
        "first_name" : "Arthur",
        "last_name" : "Pierre",
        "birth_date" : null,
        "role" : null
    }
]

wird zurückkehren

[ "artist:3", "artist:16", "artist:282" ]

Dieses Ergebnis wird mit einem Einzelelement-Array ["$directors._id"] verglichen mit dem $setIsSubset Operator, der zwei Arrays nimmt und wahr zurückgibt, wenn das erste Array eine Teilmenge des zweiten ist, einschließlich, wenn das erste Array gleich dem zweiten Array ist, und andernfalls falsch.

Zum Beispiel

{ 
    "$setIsSubset": [ 
        [ "artist:12" ], 
        [ "artist:3", "artist:16", "artist:282" ] 
    ] 
}       // false

{ 
    $setIsSubset: [ 
        [ "artist:282" ], 
        [ "artist:3", "artist:16", "artist:282" ] 
    ] 
}       // true

Das boolesche Ergebnis des Operators wird dann als Grundlage für den $redact Pipeline.

Die Erläuterungen zur Leistung gelten weiterhin:$where ist bei Bedarf ein guter Hack, sollte aber nach Möglichkeit vermieden werden.