“文档” 菜单
文档首页
/
MongoDB Manual
/ / /

$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 字段的文档。正如以下场景所示,您可以编写查询将 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 具有 SalesOperations 角色,且能看到以下文档:

[
{
_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 仍填充用户的角色。

← $setField(聚合)

在此页面上