Fra den tidligere linkede dupe (mulig)
, en løsning, der bruger $where
ville følge:
db.collection.find({
"$where": function() {
self = this;
return this.actors.filter(function(actor) {
return self.director._id === actor._id;
}).length > 0
}
})
Og den anden foreslåede tilgang, der bruger aggregeringsrammen $redact
pipeline:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$setIsSubset": [
["$director._id"],
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
I ovenstående er betingelseslogikken for $redact
sker ved brug af sætoperatorer $setIsSubset
og $map
.
$map
operatør vil returnere et array med kun aktør-id'erne fra aktørerne
array efter at have anvendt et udtryk til hvert element i arrayet. Så for eksempel udtrykket
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
hvis det anvendes på skuespillerrækken
[
{
"_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
}
]
vender tilbage
[ "artist:3", "artist:16", "artist:282" ]
Dette resultat sammenlignes med et enkelt element array ["$directors._id"]
ved hjælp af $setIsSubset
operator, der tager to arrays og returnerer sand, når det første array er en delmængde af det andet, inklusive når det første array er lig med det andet array, og ellers false.
For eksempel,
{
"$setIsSubset": [
[ "artist:12" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // false
{
$setIsSubset: [
[ "artist:282" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // true
Det boolske resultat fra operatøren bruges derefter som grundlag for $redact
pipeline.
Forklaringerne på ydeevne gælder stadig:$where
er et godt hack, når det er nødvendigt, men det bør undgås, når det er muligt.