MongoDB 中的某种联合聚合查询

Some kind of a join-aggregation query in MongoDB

在我的数据库中,我有两个集合:

Subjects Collection
 - id : ObjectID(own)
 - subjectCreator : ObjectID(of a user)
 - groups : Array
            [
                 ObjectID(of a group),
                 ObjectID(of a group),
                 ....more
            ]
 - media : Array
            [
                 { 
                     id : ObjectID(of media)
                     mediaUploader: ObjectID(of user)
                     other properties that not important
                 },
                 { 
                     id : ObjectID(of media)
                     mediaUploader: ObjectID(of user)
                     other properties that not important
                 },

            ]

和一个网上论坛集合

Groups Collection
 - id : ObjectID(own)
 - groupName: string
 - groupAdmin: ObjectID(of user)
 - members: Array
            [
                 ObjectID(of a user),
                 ObjectID(of a user),
                 ....more
            ]

我想做的是, 当给定用户 ID (ObjectID) 获取用户可以看到的所有主题的数组。

用户可以通过两个标准查看主题:

  1. 如果他们是主题创作者

  2. 如果他们是主题包含在 groups 字段中的组的成员

我理解这是两个查询之间的一种聚合, 但我无法提供自己试用的示例,因为我是 MongoDB 的新手, 甚至不知道如何处理它。

认为 (可能是错误的)如果这是在 SQL 服务器中编写的,它将看起来像这样:

给定一个@userID 参数

SELECT distinct s.* 
FROM Subjects s
WHERE @userID = s.subjectCreator
OR 
@userID in (
               SELECT members 
               FROM Groups g 
               WHERE g.GroupID in (
                                       SELECT groups 
                                       FROM Subjects
                                       WHERE s.Groups.GroupID = g.GroupID
                                   )
           )

我的服务器端是用 NodeJS 编写的

还有一个小问题,哪个是数据库结构的最佳实践? 上面的结构, 还是下面的结构? 区别在于数组,请解释原因

Subjects Collection
 - id : ObjectID(own)
 - subjectCreator : ObjectID(of a user)
 - groups : Array
            [
                 { groupID: ObjectID(of a group) },
                 { groupID: ObjectID(of a group) },,
                 ....more **OBJECTS**
            ]
 - media : Array
            [
                 { 
                     id : ObjectID(of media)
                     mediaUploader: ObjectID(of user)
                     other properties that not important
                 },
                 { 
                     id : ObjectID(of media)
                     mediaUploader: ObjectID(of user)
                     other properties that not important
                 },

            ]

和一个网上论坛集合

Groups Collection
 - id : ObjectID(own)
 - groupName: string
 - groupAdmin: ObjectID(of user)
 - members: Array
            [
                 { memberID : ObjectID(of a user) },
                 { memberID : ObjectID(of a user) },
                 ....more objects of members id
            ]

对于第一个问题,我们的策略是使用 $lookup 到 "merge" 这些集合,然后对其进行查询。

db.collection.Subjetcs.aggregate([
        {
           $lookup: {
               from: "Groups",
               let: {group_ids: "$groups"},
               pipeline: [
                    {
                       $match: {
                          $expr:  {
                              $in: ["$id", "$$group_ids"]
                          }
                       }
                    }
               ]
               as: "group" 
           }
        },
        {
           $match: {
              $or: [
                  {subjectCreator: ObjectId(givenUserID)},
                  {'group.members': ObjectId(givenUserID)}
              ]
           }
        },
])

在设计方面我会坚持使用前者,它使查询看起来 "cleaner" 并且根据我的经验,将来在将 [{_id: 1}, {_id: 2}] 转换为 [1, 2] 时会节省您的时间和资源不管什么原因。

请注意,它们是等价的 "power",即可以用它完成什么。

此外,我不确定开销有多大,但我认为在您这样做的情况下,将该字段索引为数组对于 mongo 来说要容易得多。