MongoDB 如何对数组的数组执行聚合查找

MongoDB How to perform an aggregation lookup on array of an array

是否可以像这样聚合和连接匹配数据:

application (Document) -> roles (DBRef array) -> permissions (DBRef array) -> name (String)

应用程序有角色,角色有权限,权限有名称。

我一直在努力弄清楚如何进行聚合操作来实现这种复杂的连接。我想要做的是选择具有角色权限应用程序名字。

这是我的基本示例文档:

申请:

{
    "_id": {
        "$numberLong": "11"
    },
    "name": "my-module",
    "roles": [{
        "$ref": "role",
        "$id": {
            "$numberLong": "17"
        }
    }
}

角色:

{
    "_id": {
        "$numberLong": "17"
    },
    "name": "AdminRole",
    "application": {
        "$ref": "application",
        "$id": {
            "$numberLong": "11"
        }
    },
    "permissions": [{
        "$ref": "permission",
        "$id": {
            "$numberLong": "46"
        }
    }, {
        "$ref": "permission",
        "$id": {
            "$numberLong": "49"
        }
    }]
}

权限:

{
    "_id": {
        "$numberLong": "46"
    },
    "name": "TestPermission1"
},
{
    "_id": {
        "$numberLong": "49"
    },
    "name": "TestPermission2"
}

我已经弄清楚如何从角色数组中聚合一级数据:

$lookup:
{
  from: 'role',
  localField: 'roles.$id',
  foreignField: '_id',
  as: '_roles'
}
$match: /**
 * query: The query in MQL.
 */
{
    $or: [{
      "_roles": {
        "$elemMatch": {
          state: 'DISABLED'
          /* how can also look through the roles permissions (array of DBRef) for permission data? */
        }
      },
      /* other checks */
    }]
}

感谢有关此问题的任何帮助!

谢谢!

使用此数据结构,您最好先搜索权限,然后再查找角色和应用程序。这样您就可以从 permissions 集合中的索引 name 中获益。

像这样:

db.permission.aggregate([
  {
    "$match": {
      name: "TestPermission1"
    }
  },
  {
    "$lookup": {
      "from": "role",
      "localField": "_id",
      "foreignField": "permissions.$id",
      "as": "permissions"
    }
  },
  {
    "$lookup": {
      "from": "application",
      "localField": "permissions.application.$id",
      "foreignField": "_id",
      "as": "app"
    }
  },
  {
    "$unwind": "$app"
  },
  {
    "$replaceRoot": {
      "newRoot": "$app"
    }
  }
])

附带说明一下,您不必使用 DBRef,这样使用起来会更简单一些。