mongodb 将数组中的项替换为另一个数组中匹配对象的属性

zlwx9yxi  于 2022-12-18  发布在  Go
关注(0)|答案(1)|浏览(135)

有一个permissions集合,其中包含权限以及为给定资源分配了该权限的用户或组。
permissions

[{
  "_id": 1,
  "resource": "resource:docs/61",
  "permissions": [
    {
      "permission": "role:documentOwner",
      "users": [
        "user:abc",
        "user:def",
        "group:abc",
        "group:bff"
      ]
    },
    {
      "permission": "document.read",
      "users": ["user:xxx"]
    },
    {
      "permission": "document.update",
      "users": ["user:xxx"]
    }
  ]
}]

和将用户分配到组的groups集合。
groups

[
  {
    "_id": 1,
    "id": "abc",
    "name": "Test Group",
    "users": ["cpo", "yyy"]
  },
  {
    "_id": 2,
    "id": "bff",
    "name": "Another Group",
    "users": ["xxx"]
  }
]

我正在尝试查询permissions集合中的resource:docs/61,对于每个权限,将users属性中的任何组解析为匹配组的users

预期结果

{
  "resource": "resource:docs/61",
  "permissions": [
    {
      "permission": "role:documentOwner",
      "users": [
        "user:abc",
        "user:def",
        "user:cpo",
        "user:yyy",
        "user:xxx"
      ]
    },
    {
      "permission": "document.read",
      "users": ["user:xxx"]
    },
    {
      "permission": "document.update",
      "users": ["user:xxx"]
    }
  ]
}


我安装了一个Mongo Playground,我一直在尝试让它工作......但没有成功。下面是我目前的尝试。我不知道如何将组Map到他们尊敬的用户,然后逆转$unwind。或者我甚至不需要$unwind🤷‍ ♂️

db.permissions.aggregate([
  {
    "$match": {
      "resource": "resource:docs/61"
    }
  },
  {
    $unwind: "$permissions"
  },
  {
    "$lookup": {
      "from": "groups",
      "let": {
        "users": {
          "$filter": {
            "input": "$permissions.users",
            "as": "user",
            "cond": {
              "$ne": [
                -1,
                {
                  "$indexOfCP": [
                    "$$user",
                    "group:"
                  ]
                }
              ]
            }
          }
        }
      },
      "pipeline": [
        {
          "$match": {
            "$expr": {
              "$in": [
                {
                  "$concat": [
                    "group:",
                    "$id"
                  ]
                },
                "$$users"
              ]
            }
          }
        },
        {
          "$project": {
            "_id": 0,
            "id": {
              "$concat": [
                "group:",
                "$id"
              ]
            },
            "users": 1
          }
        }
      ],
      "as": "groups"
    }
  },
  {
    "$project": {
      "groups": 1,
      "permissions": {
        "permission": "$permissions.permission",
        "users": "permissions.users"
      }
    }
  }
])
fwzugrvs

fwzugrvs1#

您需要:

  1. $unwindpermissions使后续阶段的处理更轻松
    1.带有“已处理”键的$lookup
  • 删除组密钥的前缀group:

1.使用$lookup结果对您的permissions.users数组执行$setUnion。请记住首先对组条目执行$filter

  1. $group以取回原始/预期结构。
db.permissions.aggregate([
  {
    "$match": {
      "resource": "resource:docs/61"
    }
  },
  {
    "$unwind": "$permissions"
  },
  {
    "$lookup": {
      "from": "groups",
      "let": {
        "groups": {
          "$map": {
            "input": "$permissions.users",
            "as": "u",
            "in": {
              "$replaceAll": {
                "input": "$$u",
                "find": "group:",
                "replacement": ""
              }
            }
          }
        }
      },
      "pipeline": [
        {
          $match: {
            $expr: {
              "$in": [
                "$id",
                "$$groups"
              ]
            }
          }
        }
      ],
      "as": "groupsLookup"
    }
  },
  {
    "$addFields": {
      "groupsLookup": {
        "$reduce": {
          "input": "$groupsLookup",
          "initialValue": [],
          "in": {
            $setUnion: [
              "$$value",
              {
                "$map": {
                  "input": "$$this.users",
                  "as": "u",
                  "in": {
                    "$concat": [
                      "user:",
                      "$$u"
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    "$project": {
      resource: 1,
      permissions: {
        permission: 1,
        users: {
          "$setUnion": [
            {
              "$filter": {
                "input": "$permissions.users",
                "as": "u",
                "cond": {
                  $eq: [
                    -1,
                    {
                      "$indexOfCP": [
                        "$$u",
                        "group:"
                      ]
                    }
                  ]
                }
              }
            },
            "$groupsLookup"
          ]
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      resource: {
        $first: "$resource"
      },
      permissions: {
        $push: "$permissions"
      }
    }
  }
])

Mongo Playground

相关问题