От свързано преди това дублиране (възможно)
, решение, използващо $where
ще последва:
db.collection.find({
"$where": function() {
self = this;
return this.actors.filter(function(actor) {
return self.director._id === actor._id;
}).length > 0
}
})
И другият предложен подход, който използва рамката за агрегиране $redact
тръбопровод:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$setIsSubset": [
["$director._id"],
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
В горното логиката на условието за $redact
се извършва чрез използването на набор оператори $setIsSubset
и $map
.
$map
ще върне масив само с идентификаторите на актьорите от актьорите
масив след прилагане на израз към всеки елемент в масива. Така например изразът
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
ако се приложи върху масива актьори
[
{
"_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
}
]
ще се върне
[ "artist:3", "artist:16", "artist:282" ]
Този резултат се сравнява с масив от един елемент ["$directors._id"]
използвайки $setIsSubsetкод>
оператор, който приема два масива и връща true, когато първият масив е подмножество на втория, включително когато първият масив е равен на втория масив, и false в противен случай.
Например,
{
"$setIsSubset": [
[ "artist:12" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // false
{
$setIsSubset: [
[ "artist:282" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // true
Булевият резултат от оператора след това се използва като основа за $redact
тръбопровод.
Обясненията за производителността все още са в сила:$whereкод>
е добър хак, когато е необходимо, но трябва да се избягва, когато е възможно.