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)
获取用户可以看到的所有主题的数组。
用户可以通过两个标准查看主题:
如果他们是主题创作者
如果他们是主题包含在 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 来说要容易得多。
在我的数据库中,我有两个集合:
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) 获取用户可以看到的所有主题的数组。
用户可以通过两个标准查看主题:
如果他们是主题创作者
如果他们是主题包含在
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 来说要容易得多。