Từ bản dupe được liên kết trước đó (có thể)
, một giải pháp sử dụng $ where
sẽ theo dõi:
db.collection.find({
"$where": function() {
self = this;
return this.actors.filter(function(actor) {
return self.director._id === actor._id;
}).length > 0
}
})
Và cách tiếp cận được đề xuất khác sử dụng khung tổng hợp $ redact
đường ống:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$setIsSubset": [
["$director._id"],
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Ở trên, logic điều kiện cho $ redact
được thực hiện thông qua việc sử dụng các toán tử tập hợp $ setIsSubset
và $ map
.
$ map
toán tử sẽ trả về một mảng chỉ có id của tác nhân từ Actor
mảng sau khi áp dụng một biểu thức cho từng phần tử trong mảng. Ví dụ:biểu thức
{
"$map": {
"input": "$actors",
"as": "el",
"in": "$$el._id"
}
}
nếu được áp dụng trên mảng tác nhân
[
{
"_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
}
]
sẽ trở lại
[ "artist:3", "artist:16", "artist:282" ]
Kết quả này được so sánh với một mảng phần tử duy nhất ["$ director._id"]
sử dụng $ setIsSubset
toán tử nhận hai mảng và trả về true khi mảng đầu tiên là tập con của mảng thứ hai, bao gồm cả khi mảng đầu tiên bằng mảng thứ hai và false nếu không.
Ví dụ:
{
"$setIsSubset": [
[ "artist:12" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // false
{
$setIsSubset: [
[ "artist:282" ],
[ "artist:3", "artist:16", "artist:282" ]
]
} // true
Kết quả boolean từ toán tử sau đó được sử dụng làm cơ sở cho $ redact
đường ống dẫn.
Các giải thích cho hiệu suất vẫn được giữ nguyên: $ where
là một cách hack tốt khi cần thiết, nhưng nên tránh nó bất cứ khi nào có thể.