如何将两个不同查询的结果与猫鼬结合在一起?

问题描述 投票:1回答:1

我有3个模型(项目,组织,用户),其架构如下所示。我正在使用mongo版本4.2.0和Moongoose版本5.1.1。

问题

给特定的用户,我如何查询他们有权访问的所有项目:

  • 通过项目本身的直接角色

  • 或通过该项目所属组织的直接角色

用户可以在组织中发挥作用,但在其项目中可能没有。尽管如此,查询仍应能够获取这些项目(用户具有上级访问权限)。

示例

Projects
[
    {    
        "_id" : ObjectId("1184f3c454b1fd6926c324fd"),
        "organizationId" : ObjectId("1284f3c454b1fd6926c324fd"),
        "roles" : [
            {
                user: ObjectId("1314f3c454b1fd6926c324fd"),
                role: 'Bar'
            }
        ]
    },
    {    
        "_id" : ObjectId("1172f3c454b1fd6926c324fd"),
        "organizationId" : ObjectId("1284f3c454b1fd6926c324fd"),
        "roles" : [
            {
                user: ObjectId("1313f4c584b1fd6926c324fd"),
                role: 'Bar'
            }
        ]
    }
]

Organizations
{    
    "_id" : ObjectId("1284f3c454b1fd6926c324fd"),
    "roles" : [
        {
            user: ObjectId("1314f3c454b1fd6926c324fd"),
            role: 'Bar'
        }
    ]
}

Users
{    
    "_id" : ObjectId("1314f3c454b1fd6926c324fd"),
    "name": "Foo"
}

[Notes

  • 这两个项目属于同一组织。

  • 用户“ Foo”属于此组织,但只能直接访问其项目之一。

  • 有问题的查询应为用户“ Foo”返回两个项目

应该将两个不同的查询合并吗?

mongodb mongoose mongoose-populate
1个回答
0
投票

使用aggregation管道,您可以实现此查询:

db.Projects.aggregate([
  {
    $lookup: {
      from: "Organizations",
      localField: "organizationId",
      foreignField: "_id",
      as: "organization"
    }
  },
  {
    $match: {
      $or: [
        {
          "roles.user": varSpecificUserId
        },
        {
          "organization.roles.user": varSpecificUserId
        }
      ]
    }
  }
]);

这里是EXPLANATIONS,来自以下数据库数据:

Projects
[
    {
      "_id": "pro0",
      "organizationId": "org0",
      "roles": []
    },
    {
      "_id": "pro2",
      "organizationId": "org1",
      "roles": []
    },
    {
      "_id": "pro3",
      "organizationId": "org0",
      "roles": [
        {
          user: "usr2",
          role: "Foo"
        }
      ]
    }
  ]

Organizations
[
    {
      "_id": "org0",
      "roles": [
        {
          user: "usr0",
          role: "Foo"
        }
      ]
    },
    {
      "_id": "org1",
      "roles": [
        {
          user: "usr1",
          role: "Bar"
        }
      ]
    }
  ],
Users
[{
    "_id": "usr0",
    "name": "User0"
},
{
    "_id": "usr1",
    "name": "User1"
},
    {
      "_id": "usr2",
      "name": "User2"
    },
    {
      "_id": "usr3",
      "name": "User3"
    }
  ]
}
  • 让我们呼叫varSpecificUserId specific user'_id。
  • [$lookup使用来自localField集合的Projects与来自foreignField集合的Organizations匹配的另一个集合。
  • $lookup的结果是所有Organizations的数组,如果每个organizationId都与Project匹配。使用organisation对象的as关键字将该数组存储在$lookup。这是前查询对象在此步骤:
{
    "_id": "pro0",
    "organization": [
      {
        "_id": "org0",
        "roles": [
          {
            "role": "Foo",
            "user": "usr0"
          }
        ]
      }
    ],
    "organizationId": "org0",
    "roles": []
  },
  • organization现在附加到Project,我们具有执行查询的所有信息:

    • 或者通过在项目本身中的直接角色
    • 或通过项目所属组织的直接角色
  • $match步骤将在Projects数组中具有匹配的userrolesvarSpecificUserId变量OR保持在userorganization中的匹配roles数组。这是使用varSpecificUserId = "usr0"的最终查询结果:

[
  {
    "_id": "pro0",
    "organization": [
      {
        "_id": "org0",
        "roles": [
          {
            "role": "Foo",
            "user": "usr0"
          }
        ]
      }
    ],
    "organizationId": "org0",
    "roles": []
  },
  {
    "_id": "pro3",
    "organization": [
      {
        "_id": "org0",
        "roles": [
          {
            "role": "Foo",
            "user": "usr0"
          }
        ]
      }
    ],
    "organizationId": "org0",
    "roles": [
      {
        "role": "Foo",
        "user": "usr2"
      }
    ]
  }
]

如果您已经有数据库中的数据,则可以使用https://mongoplayground.net/来处理mongo查询或MongoDB Compass中的新聚合工具。

© www.soinside.com 2019 - 2024. All rights reserved.