sql >> Base de Datos >  >> NoSQL >> MongoDB

Buscar elemento basado en dos valores

Del dupe previamente vinculado (posible) , una solución que usa $where seguiría:

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

Y el otro enfoque sugerido que utiliza el marco de agregación $redactar canalización:

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

En lo anterior, la lógica de condición para $redactar se realiza mediante el uso de operadores de conjuntos código>$setIsSubset y $map .

El $map El operador devolverá una matriz con solo la identificación del actor de los actores matriz después de aplicar una expresión a cada elemento de la matriz. Entonces, por ejemplo, la expresión

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

si se aplica en la matriz de actores

[ 
    {
        "_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
    }
]

regresará

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

Este resultado se compara con una matriz de un solo elemento ["$directors._id"] usando el $setIsSubset operador que toma dos matrices y devuelve verdadero cuando la primera matriz es un subconjunto de la segunda, incluso cuando la primera matriz es igual a la segunda matriz, y falso en caso contrario.

Por ejemplo,

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

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

El resultado booleano del operador se usa como base para $redact canalización.

Las explicaciones del rendimiento aún se mantienen:$where es un buen truco cuando es necesario, pero debe evitarse siempre que sea posible.