MongoDB按$ lookup数组过滤查询结果

时间:2019-10-30 12:11:20

标签: php mongodb

MongoDB 3.4 我有一个项目 project_permission 集合。 project_permission集合包含某些用户对项目的权限。一个用户可以对该项目具有多个不同的权限。

        [
            '$lookup' => [
                'from' => ProjectPermission::collectionName(),
                'localField' => '_id',
                'foreignField' => 'project_id',
                'as' => 'project_permissions'
            ]
        ],
        [
            '$project' => [
                // ... irrelevant fields here
                'permissions' => '$project_permissions'
            ]
        ],

这是未经过滤的项目查询结果的样子:

  // other project results
      // ... other fields
      'permissions' => [
          0 => [
              '_id' => '5d2873aafa873b2b7c000fad'
              'project_id' => '56a9e5c5d18cacc72a485839'
              'user_id' => '562f6bfc05dfe9570fb6e427'
              'permission' => 'read'
              'created_at' => 1562932138
              'updated_at' => 1562932139
          ]
          1 => [
              '_id' => '5d2879fdfa873b2b7c000fbd'
              'project_id' => '56a9e5c5d18cacc72a485839'
              'user_id' => '562f6bfc05dfe9570fb6e427'
              'permission' => 'write'
              'created_at' => 1562932139
              'updated_at' => 1562932140
          ]
          2 => [
              '_id' => '5db960b5fa873b1604005e8e'
              'project_id' => '56a9e5c5d18cacc72a485839'
              'user_id' => '582b30dd1e634e6362e1b504'
              'permission' => 'write'
              'created_at' => 1572430005
              'updated_at' => 1572430005
          ]
      ]

我想实现的是仅返回那些请求查询的客户端对项目具有特定权限(例如写)的项目。

我尝试的方式:

pipeline: [
    0 => [
        '$match' => [
            // not related to the problem
        ]
    ]
    1 => [
        '$match' => [
            '$and' => [
                0 => [
                    'shared_permissions' => [
                        '$eq' => true
                    ]
                ]
                1 => [
                    '$or' => [
                        0 => [
                            'project_permissions' => [
                                '$exists' => true
                                '$ne' => []
                            ]
                        ]
                        1 => [
                            'owner_id' => [
                                '$ne' => MongoDB\BSON\ObjectId#1
                                (
                                    [oid] => '582b30dd1e634e6362e1b504'
                                )
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
    2 => [
        '$lookup' => [
            'from' => 'project_permission'
            'localField' => '_id'
            'foreignField' => 'project_id'
            'as' => 'project_permissions'
        ]
    ]
    3 => [
        '$project' => [
            // more not important fields here
            'shared_permissions' => 1
            'permissions' => [
                '$map' => [
                    'input' => [
                        '$filter' => [
                            'input' => '$project_permissions'
                            'as' => 'project_permission'
                            'cond' => [
                                '$and' => [
                                    0 => [
                                        '$eq' => ['$$project_permission.user_id', MongoDB\BSON\ObjectId#1
                                (
                                    [oid] => '582b30dd1e634e6362e1b504'
                                )
                                    ]
                                    1 => [
                                        '$eq' => ['$$project_permission.permission', 'write']
                                    ]
                                ]
                            ]
                        ]
                    ]
                    'as' => 'project_permission'
                    'in' => [
                        'user_id' => '$$project_permission.user_id'
                        'permission' => '$$project_permission.permission'
                    ]
                ]
            ]
        ]
    ]
]

为此,我几乎得到了正确的答案:

[
  0 => [
      '_id' => '56a9e5c5d18cacc72a485839'
      'short_id' => 3
      'title' => 'Modified title'
      'owner_id' => '562f692a05dfe9560fb6e428'
      'updated_at' => 1572435428
      'owner_name' => 'Borat Sagdiyev'
      'shared_permissions' => true
      'permissions' => [
          0 => [
              'user_id' => '582b30dd1e634e6362e1b504'
              'permission' => 'write'
          ]
      ]
  ]
  1 => []

]

这个问题是空数组,结果被过滤掉了-如果结果中没有空数组也就不成问题,因为如果我使用分页,那么它说两个结果,而不是一个。而且我们知道,在最坏的情况下,我们只会得到一个空数组。 因此,我想实现的是最后一个示例结果,它没有空数组,因此分页也可以。

ps .:由于某些结构上的约定,因此不能选择展开。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

要在输入文档中的字段与“ joined”集合的文档中的字段之间执行相等匹配,$ lookup阶段具有以下语法:

{
$lookup:
 {
   from: <collection to join>,
   localField: <field from the input documents>,
   foreignField: <field from the documents of the "from" collection>,
   as: <output array field>
 }
 }