MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Trova l'elemento in base a due valori

Dal dupe precedentemente collegato (possibile) , una soluzione che utilizza $where seguirebbe:

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

E l'altro approccio suggerito che utilizza il framework di aggregazione $redact pipeline:

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

In quanto sopra, la logica della condizione per $redact avviene tramite l'uso di operatori di insiemi $setIsSubset e $map .

Il $map l'operatore restituirà un array con solo gli ID attore da actors array dopo aver applicato un'espressione a ciascun elemento nell'array. Quindi, ad esempio, l'espressione

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

se applicato all'array attori

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

tornerà

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

Questo risultato viene confrontato con un array a elemento singolo ["$directors._id"] utilizzando $setIsSubset operatore che accetta due array e restituisce true quando il primo array è un sottoinsieme del secondo, incluso quando il primo array è uguale al secondo array, e false in caso contrario.

Ad esempio,

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

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

Il risultato booleano dell'operatore viene quindi utilizzato come base per $redact pipeline.

Le spiegazioni per le prestazioni sono ancora valide:$where è un buon hack quando necessario, ma dovrebbe essere evitato quando possibile.