MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Localizar elemento com base em dois valores


Do dupe vinculado anteriormente (possível) , uma solução usando $where seguiria:
db.collection.find({
    "$where": function() {
        self = this;
        return this.actors.filter(function(actor) {
            return self.director._id === actor._id;
        }).length > 0
    }
})

E a outra abordagem sugerida que usa a estrutura de agregação $redact encanamento:
db.collection.aggregate([
    { 
        "$redact": { 
            "$cond": [
                { 
                    "$setIsSubset": [ 
                        ["$director._id"], 
                        {
                            "$map": {
                                "input": "$actors",
                                "as": "el",
                                "in": "$$el._id"
                            }
                        }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

Acima, a lógica de condição para $redact é feito através do uso de operadores de conjunto $setIsSubset e $map .

O $map operador retornará um array com apenas os IDs dos atores dos atores array depois de aplicar uma expressão a cada elemento no array. Assim, por exemplo, a expressão
{
    "$map": {
        "input": "$actors",
        "as": "el",
        "in": "$$el._id"
    }
}

se aplicado na matriz de atores
[ 
    {
        "_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
    }
]

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

Este resultado é comparado com um array de elemento único ["$directors._id"] usando o $setIsSubset operador que recebe dois arrays e retorna true quando o primeiro array é um subconjunto do segundo, inclusive quando o primeiro array é igual ao segundo array e false caso contrário.

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

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

O resultado booleano do operador é usado como base para o $redact encanamento.

As explicações para o desempenho ainda são válidas:$where é um bom hack quando necessário, mas deve ser evitado sempre que possível.