将聚合框架与 $redact 管道运算符一起使用,您可以使用 $cond 运算符处理逻辑条件并使用特殊操作 @ 987654323@“保留”逻辑条件为真的文档或$$PRUNE“删除”条件为假的文档。
此操作类似于具有 $project 管道,它选择集合中的字段并创建一个新字段来保存逻辑条件查询的结果,然后是后续 @ 987654326@,除了 $redact 使用更高效的单个流水线阶段。
至于逻辑条件,您可以使用Set Operators,因为它们允许对数组执行集合操作的表达式,将数组视为集合。设置表达式忽略每个输入数组中的重复条目和元素的顺序,这在您的情况下是一个合适的属性,因为您
想要忽略元素的顺序。
您可以使用其中几个运算符来执行逻辑条件,即 $setIsSubset 和 $setDifference。
考虑以下证明上述概念的示例:
填充测试集合
db.collection.insert([
{ users: ['user1', 'user2'] },
{ users: ['user1', 'user2', 'user2'] },
{ users: ['user1', 'user2', 'user3'] },
{ users: ['user1', 'user3'] },
])
示例 1: $redact 与 $setEquals
var arr = [ "user2", "user1" ];
db.collection.aggregate([
{
"$redact": {
"$cond": [
{ "$setEquals": [ "$users", arr ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
样本输出
/* 1 */
{
"_id" : ObjectId("5804902900ce8cbd028523d1"),
"users" : [
"user1",
"user2"
]
}
/* 2 */
{
"_id" : ObjectId("5804902900ce8cbd028523d2"),
"users" : [
"user1",
"user2",
"user2"
]
}
示例 2: $redact 与 $setDifference
var arr = [ "user2", "user1" ];
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$eq": [
{ "$setDifference": [ "$users", arr ] },
[]
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
样本输出
/* 1 */
{
"_id" : ObjectId("5804902900ce8cbd028523d1"),
"users" : [
"user1",
"user2"
]
}
/* 2 */
{
"_id" : ObjectId("5804902900ce8cbd028523d2"),
"users" : [
"user1",
"user2",
"user2"
]
}
另一种方法,虽然只在 $redact 不可用时推荐,但将 $where 运算符用作:
db.collection.find({
"$where": function() {
var arr = ["user2", "user1"];
return !(this.users.sort() > arr.sort() || this.users.sort() < arr.sort());
}
})
但是,请记住,这不会很好,因为使用 $where 运算符的查询操作会调用 JavaScript 引擎来评估每个文档上的 JavaScript 代码并检查每个文档的条件.
这非常慢,因为 MongoDB 在 $where 表达式和非$where 查询之前评估非$where 查询操作语句可以使用索引。
如果可以的话,建议结合索引查询,这样查询可能会更快。但是,当您无法以任何其他方式构造数据或处理一小部分数据时,建议您使用 JavaScript 表达式和 $where 运算符作为最后的手段。