Du dupe précédemment lié (possible)
, une solution utilisant $where
suivrait :
db.collection.find({
"$where": function() {
self = this;
return this.actors.filter(function(actor) {
return self.director._id === actor._id;
}).length > 0
}
})
Et l'autre approche suggérée qui utilise le cadre d'agrégation $redact
pipeline :
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$setIsSubset": [
["$director._id"],
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Dans ce qui précède, la logique de condition pour $redact
se fait grâce à l'utilisation d'opérateurs d'ensemble $setIsSubset
et $map
.
Le $map
L'opérateur renverra un tableau contenant uniquement les identifiants d'acteur des actors
tableau après avoir appliqué une expression à chaque élément du tableau. Ainsi, par exemple, l'expression
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
si appliqué sur le tableau des acteurs
[
{
"_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
}
]
reviendra
[ "artist:3", "artist:16", "artist:282" ]
Ce résultat est comparé à un tableau à un seul élément ["$directors._id"]
en utilisant le $setIsSubset
opérateur qui prend deux tableaux et renvoie true lorsque le premier tableau est un sous-ensemble du second, y compris lorsque le premier tableau est égal au second tableau, et false sinon.
Par exemple,
{
"$setIsSubset": [
[ "artist:12" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // false
{
$setIsSubset: [
[ "artist:282" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // true
Le résultat booléen de l'opérateur est ensuite utilisé comme base pour le $redact
pipeline.
Les explications sur les performances sont toujours valables :$where
est un bon hack si nécessaire, mais il doit être évité autant que possible.