文档菜单
文档首页
/
MongoDB 手册
/ / /

$setIntersection (聚合)

本页面

  • 定义
  • 行为
  • 示例
$setIntersection

接受两个或多个数组,并返回一个包含每个输入数组中出现的元素的数组。

$setIntersection具有以下语法

{ $setIntersection: [ <array1>, <array2>, ... ] }

参数可以是任何有效的表达式,只要它们每个解析为一个数组。有关表达式的更多信息,请参阅表达式运算符。

$setIntersection对数组执行集合运算,将数组视为集合。如果数组包含重复条目,$setIntersection会忽略重复条目。$setIntersection忽略元素顺序。

$setIntersection 会过滤掉结果中的重复项,以输出只包含唯一条目的数组。输出数组中元素的顺序是不确定的。

如果没有找到交集(即输入数组中没有共同元素),$setIntersection 将返回一个空数组。

如果集合包含嵌套数组元素,$setIntersection 不会进入嵌套数组,而是在顶级评估数组。

示例
结果
{ $setIntersection: [ [ "a", "b", "a" ], [ "b", "a" ] ] }
[ "b", "a" ]
{ $setIntersection: [ [ "a", "b" ], [ [ "a", "b" ] ] ] }
[ ]

本节包含示例,展示了如何使用 $setIntersection 与集合一起使用。

假设有一个包含以下文档的 flowers 集合

db.flowers.insertMany( [
{ "_id" : 1, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid" ] },
{ "_id" : 2, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "orchid", "rose", "orchid" ] },
{ "_id" : 3, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid", "jasmine" ] },
{ "_id" : 4, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "jasmine", "rose" ] },
{ "_id" : 5, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ ] },
{ "_id" : 6, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose" ], [ "orchid" ] ] },
{ "_id" : 7, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose", "orchid" ] ] },
{ "_id" : 8, "flowerFieldA" : [ ], "flowerFieldB" : [ ] },
{ "_id" : 9, "flowerFieldA" : [ ], "flowerFieldB" : [ "rose" ] }
] )

以下操作使用 $setIntersection 操作符返回 flowerFieldA 数组和 flowerFieldB 数组共有的元素数组

db.flowers.aggregate(
[
{ $project: { flowerFieldA: 1, flowerFieldB: 1, commonToBoth: { $setIntersection: [ "$flowerFieldA", "$flowerFieldB" ] }, _id: 0 } }
]
)

操作返回以下结果

{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "orchid", "rose", "orchid" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid", "jasmine" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "jasmine", "rose" ], "commonToBoth" : [ "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose" ], [ "orchid" ] ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose", "orchid" ] ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ ], "flowerFieldB" : [ ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ ], "flowerFieldB" : [ "rose" ], "commonToBoth" : [ ] }

从 MongoDB 7.0 版本开始,您可以使用新的 USER_ROLES 系统变量来返回用户 角色。

本节中的场景展示了具有各种角色的用户,他们对包含预算信息的集合中的文档具有有限的访问权限。

此场景展示了 USER_ROLES 的一种可能的用途。在 budget 集合中,文档包含一个名为 allowedRoles 的字段。正如您将在以下场景中看到的那样,您可以编写查询,将这些字段中找到的用户角色与由 USER_ROLES 系统变量返回的角色进行比较。

注意

有关另一个 USER_ROLES 示例场景,请参阅 检索授予当前用户的医疗信息。该示例不将用户角色存储在文档字段中,而下面的示例则这样做。

对于本节中的预算场景,执行以下步骤以创建角色、用户和 budget 集合

1

运行

db.createRole( { role: "Marketing", roles: [], privileges: [] } )
db.createRole( { role: "Sales", roles: [], privileges: [] } )
db.createRole( { role: "Development", roles: [], privileges: [] } )
db.createRole( { role: "Operations", roles: [], privileges: [] } )
2

创建名为 JohnJane 的用户,并分配所需的角色。将 test 数据库替换为您的数据库名称。

db.createUser( {
user: "John",
pwd: "jn008",
roles: [
{ role: "Marketing", db: "test" },
{ role: "Development", db: "test" },
{ role: "Operations", db: "test" },
{ role: "read", db: "test" }
]
} )
db.createUser( {
user: "Jane",
pwd: "je009",
roles: [
{ role: "Sales", db: "test" },
{ role: "Operations", db: "test" },
{ role: "read", db: "test" }
]
} )
3

运行

db.budget.insertMany( [
{
_id: 0,
allowedRoles: [ "Marketing" ],
comment: "For marketing team",
yearlyBudget: 15000
},
{
_id: 1,
allowedRoles: [ "Sales" ],
comment: "For sales team",
yearlyBudget: 17000,
salesEventsBudget: 1000
},
{
_id: 2,
allowedRoles: [ "Operations" ],
comment: "For operations team",
yearlyBudget: 19000,
cloudBudget: 12000
},
{
_id: 3,
allowedRoles: [ "Development" ],
comment: "For development team",
yearlyBudget: 27000
}
] )

按照以下步骤检索 John 可访问的文档

1

运行

db.auth( "John", "jn008" )
2

要使用系统变量,请将 $$ 添加到变量名开头。指定 USER_ROLES 系统变量为 $$USER_ROLES

运行

db.budget.aggregate( [ {
$match: {
$expr: {
$not: {
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
}
}
}
} ] )

上一个示例返回了来自 budget 集合的文档,这些文档至少匹配运行该示例的用户具有的一个角色。为了做到这一点,示例使用 $setIntersection 来返回文档,其中 budget 文档的 allowedRoles 字段与 $$USER_ROLES 中的用户角色集合的交集不为空。

3

John 拥有 MarketingOperationsDevelopment 角色,并可以看到这些文档

[
{
_id: 0,
allowedRoles: [ 'Marketing' ],
comment: 'For marketing team',
yearlyBudget: 15000
},
{
_id: 2,
allowedRoles: [ 'Operations' ],
comment: 'For operations team',
yearlyBudget: 19000,
cloudBudget: 12000
},
{
_id: 3,
allowedRoles: [ 'Development' ],
comment: 'For development team',
yearlyBudget: 27000
}
]

执行以下步骤以检索 Jane 可访问的文档

1

运行

db.auth( "Jane", "je009" )
2

要使用系统变量,请将 $$ 添加到变量名开头。指定 USER_ROLES 系统变量为 $$USER_ROLES

运行

db.budget.aggregate( [ {
$match: {
$expr: {
$not: {
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
}
}
}
} ] )
3

Jane 拥有 销售运营 角色,并查看这些文档

[
{
_id: 1,
allowedRoles: [ 'Sales' ],
comment: 'For sales team',
yearlyBudget: 17000,
salesEventsBudget: 1000
},
{
_id: 2,
allowedRoles: [ 'Operations' ],
comment: 'For operations team',
yearlyBudget: 19000,
cloudBudget: 12000
}
]

注意

在分片集群上,可以由其他服务器节点代表用户在分片上执行查询。在这些查询中,USER_ROLES 仍然填充了用户的角色。

返回

设置字段