MongoDB聚合运算符:$setIntersection

本文详细介绍了MongoDB中的$setIntersection聚合运算符,通过示例展示了如何在查询中计算数组交集,以及如何结合用户角色权限进行文档检索。
摘要由CSDN通过智能技术生成

MongoDB聚合运算符:$setIntersection


$setIntersection聚合运算符返回两个或多个数组的交集。

语法

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

字段说明:

参数可以是任何有效的数组表达式。

使用

  • $setIntersection 对数组执行集合操作,将数组视为集合,如果数组包含重复元素,$setIntersection会忽略重复元素,$setIntersection忽略元素的顺序。
  • $setIntersection 过滤掉结果中的重复项,输出仅包含唯一元素的数组,输出数组中元素的顺序未指定。
  • 如果未找到交集(即输入数组不包含公共元素),则 $setIntersection 返回一个空数组。
  • 如果集合包含嵌套数组元素,则 $setIntersection 不会下降到嵌套数组,而处理顶层数组。
例如结果
{ $setIntersection: [ [ "a", "b", "a" ], [ "b", "a" ] ] }[ "b", "a" ]
{ $setIntersection: [ [ "a", "b" ], [ [ "a", "b" ] ] ] }[]

举例

元素数组举例

使用下面的脚本创建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 系统变量来返回用户角色。

下面的例子展示了不同角色的用户对budget集合中的文档具有不同的访问权限。展示了 USER_ROLES 在进行权限检索时的一种用途,budget集合包含的文档中有一个名为 allowedRoles 的字段,在下面的场景中将会看到,可以编写查询,将 allowedRoles 字段中的用户角色与 USER_ROLES 系统变量返回的角色进行比较。

执行以下步骤创建角色、用户和budget集合:

创建角色
db.createRole( { role: "Marketing", roles: [], privileges: [] } )
db.createRole( { role: "Sales", roles: [], privileges: [] } )
db.createRole( { role: "Development", roles: [], privileges: [] } )
db.createRole( { role: "Operations", roles: [], privileges: [] } )
创建用户

创建名为 JohnJane 的用户,并设置所需的角色。

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" }
   ]
} )
创建集合
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 可以访问的文档:

使用John登录
db.auth( "John", "jn008" )
检索文档

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

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

上例从budget集合中返回与运行该示例的用户角色匹配的文档,使用 $setIntersection 返回budget文档 allowedRoles 字段与 $$USER_ROLES 中的用户角色集之间的交集不为空的文档。

检查文档

John 担任营销、运营和开发角色:

[
   {
      _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 可访问的文档:

使用Jane登录
db.auth( "Jane", "je009" )
检索文档

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

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

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
   }
]
  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原子星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值