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

时间:2019-11-30 08:37:14

标签: mongodb mongoose mongoose-populate

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

注释

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

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

  • 相关查询应为用户“ Foo”返回两个项目

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

1 个答案:

答案 0 :(得分:1)

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

    • 直接在项目本身中扮演角色
    • 或通过在项目所属组织中的直接角色
  • $match步骤将Projects数组中与user变量{strong> OR roles的{​​{1}}数组中的匹配varSpecificUserId。这是user的最终查询结果:

organization

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