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.