所以我试图在查询中“加入”3个不同的mongo集合。所以我需要的是mongo聚合中的多个$lookup
和$group
语句。
我的3个系列看起来像这样:
用户:(伪代码)
{
_id,
username: String,
group: <some group._id>
}
基团:
{
_id,
name: String,
_parent: <another group._id>,
}
列表(这些是用户拥有的“商品列表”):
{
_id,
name: String,
userId: <some user._id>
}
所以我想做的是,给定一些组ID或null
(对于没有父级的组 - 最高级别的组) - 获取该组内的所有groups
,找到所有这些群组中的users
以及lists
。
所以最后我需要这样的东西:
[
{
_id: someGroupId,
name: someGroupName,
type: "group",
users: [
{
_id: someUserId,
name: someUserName,
type: "user",
lists: [
... and the same again for the lists (type: "list")
]
},
... another user
]
},
... another group
]
我希望你理解我的意思!
我现在拥有的(感谢Simon Tretter和大量研究) - 请不要介意Meteor不可知的语法,你明白了:
Groups.aggregate([
{ $match: { _parent: groupId } },
{ $sort: { name: 1 } },
{
$lookup: {
from: 'users',
localField: '_id',
foreignField: 'group',
as: 'users'
}
},
{
$unwind: {
path: "$users",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: 'lists',
localField: 'users._id',
foreignField: 'userId',
as: 'users.lists'
}
},
{
$unwind: {
path: "$users.lists",
preserveNullAndEmptyArrays: true
}
},
{
$match: {
$or: [
{ "users.lists": { $exists: false } },
{ "users.lists.supplier_id": supplierId }
]
}
},
{ $sort: { "users.lists.name": 1 } },
{
$project: {
"name": 1,
"type": { $literal: 'group' },
"users._id": 1,
"users.name": { $ifNull: ["$users.profile.company.name", "$users.username"] },
"users.type": { $literal: 'user' },
"users.lists._id": 1,
"users.lists.name": 1,
"users.lists.item_count": 1,
"users.lists.type": { $literal: 'list' }
}
},
{
$group: {
_id: '$users._id',
name: { $first: "$users.name" },
type: { $first: "$users.type" },
children: {
$push: "$users.lists"
}
}
},
{ $sort: { "users.name": 1 } },
// until here I have one document per user, with their lists inside the "children" key - all good!
// now I have to group the users inside their groups ...
// NOT WORKING: returns completely wrong stuff
{ $group: {
_id: '$_id',
name: { $first: "$name" },
type: { $first: "$type" },
children: {
$push: "$users"
}
} },
{ $sort: { name: 1 } }
]);
我希望有人可以让我走上正确的轨道......我能找到的最好的similar stackoverflow question并没有帮助我。
非常感谢,P
答案 0 :(得分:2)
感谢@Veeram的帮助和一点点调整,我得到了以下工作代码:
Groups.aggregate([
{ $match: { _parent: groupId } },
{ $sort: { name: 1 } },
{
$lookup: {
from: 'users',
localField: '_id',
foreignField: 'group',
as: 'users'
}
},
{
$unwind: {
path: "$users",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: 'lists',
localField: 'userId',
foreignField: 'users._id',
as: 'users.lists'
}
},
{
$unwind: {
path: "$users.lists",
preserveNullAndEmptyArrays: true
}
},
{
$match: {
$or: [
{ "users.lists": { $exists: false } },
{ "users.lists.supplier_id": supplierId }
]
}
},
{ $sort: { "users.lists.name": 1 } },
{
$project: {
"name": 1,
"type": { $literal: 'group' },
"users._id": 1,
"users.name": { $ifNull: ["$users.profile.company.name", "$users.username"] },
"users.type": { $literal: 'user' },
"users.lists._id": 1,
"users.lists.name": 1,
"users.lists.item_count": 1,
"users.lists.type": { $literal: 'list' }
}
},
{
$group: {
_id: {
_id: "$_id",
name: "$name",
type: "$type",
user_id: "$users._id"
},
user_id: {
$first: "$users._id"
},
name: {
$first: "$users.name"
},
type: {
$first: "$users.type"
},
children: {
$push: "$users.lists"
}
}
},
{ $sort: { name: 1 } },
{
$group: {
_id: "$_id._id",
name: {
$first: "$_id.name"
},
type: {
$first: "$_id.type"
},
children: {
$push: {
_id: "$user_id",
name: "$name",
type: "$type",
children: "$children"
}
}
}
},
{ $sort: { name: 1 } }
]);
答案 1 :(得分:1)
未经测试,但我会尝试这样的事情:
db.groups.aggregate(
[
{ $match: { _parent: groupId } },
{
$lookup: {
from: 'users',
localField: '_id',
foreignField: 'group',
as: 'users'
}
},
{ $unwind: "$users" },
{ $lookup: {
from: 'lists',
localField: 'userId',
foreignField: 'users._id',
as: 'users.lists'
}
},
{ $group: {
_id: "$_id",
groupname: { $first: "$name" },
users: {
$push: "$users"
}
} }
])
答案 2 :(得分:1)
您必须在评论后使用group
中的_id: {_id: "$_id", name: "$name", type: "$type", user_id: "$users._id" }
($group
)信息。
像
这样的东西{
$group: {
_id: {
_id: "$_id",
name: "$name",
type: "$type",
user_id: "$users._id"
},
name: {
$first: "$users.name"
},
type: {
$first: "$users.type"
},
children: {
$push: "$users.lists"
}
}
}, {
$sort: {
name: 1
}
}, {
$group: {
_id: "$_id._id",
name: {
$first: "$_id.name"
},
type: {
$first: "$_id.type"
},
users: {
$push: {
_id:"$user_id",
name: "$name",
type: "$type",
children: "$children"
}
}
}
}