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

How to combine the results of two different queries with mongoose?

我有 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"
}

备注

是否应该合并两个不同的查询?

使用 aggregation 管道,您可以使用这个:

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

这是来自以下数据库数据的解释

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 使用 Projects 集合中的 localFieldOrganizations 集合中的 foreignField 匹配来查询其他集合。
  • $lookup 的结果是所有 OrganizationsorganizationId 匹配的数组,如果每个 Project。该数组使用 $lookup 对象的 as 关键字存储在 organisation 处。这是一个前任。这一步查询对象的数量:
{
    "_id": "pro0",
    "organization": [
      {
        "_id": "org0",
        "roles": [
          {
            "role": "Foo",
            "user": "usr0"
          }
        ]
      }
    ],
    "organizationId": "org0",
    "roles": []
  },
  • organization 现在附加到 Project,我们有执行查询的所有信息:

    • 通过项目本身的直接角色
    • 或通过项目所属组织中的直接角色
  • $match 步骤保留 Projectsroles 数组中具有匹配的 uservarSpecificUserId 变量 OR organizationroles 数组中的匹配 user。这是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 的新聚合工具。