Från den tidigare länkade dup (möjligt)
, en lösning som använder $where
skulle följa:
db.collection.find({
"$where": function() {
self = this;
return this.actors.filter(function(actor) {
return self.director._id === actor._id;
}).length > 0
}
})
Och det andra föreslagna tillvägagångssättet som använder aggregeringsramverket $redact
pipeline:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$setIsSubset": [
["$director._id"],
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
I ovanstående, villkorslogiken för code>$redact
görs med hjälp av setoperatorer $setIsSubset
och $map
.
$map
Operatören returnerar en array med bara aktörs-id:n från aktörerna
array efter att ha tillämpat ett uttryck på varje element i arrayen. Så till exempel uttrycket
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
om det tillämpas på skådespelaruppsättningen
[
{
"_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
}
]
kommer tillbaka
[ "artist:3", "artist:16", "artist:282" ]
Detta resultat jämförs med en enstaka elementarray ["$directors._id"]
med $setIsSubset
operator som tar två arrayer och returnerar true när den första arrayen är en delmängd av den andra, inklusive när den första arrayen är lika med den andra arrayen, och annars false.
Till exempel,
{
"$setIsSubset": [
[ "artist:12" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // false
{
$setIsSubset: [
[ "artist:282" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // true
Det booleska resultatet från operatören används sedan som grund för $redact
pipeline.
Förklaringarna till prestanda gäller fortfarande:$where
är ett bra hack när det behövs, men det bör undvikas när det är möjligt.