我有一个数据库,其中包含一些属于团队的用户。每个团队都有一个领导者。每个用户都有一个主题。
我想按领导者的主题整理团队。
我的数据如下:
db={
"teams": [
{
_id: "t1",
members: [
{
"_id": "u1",
"leader": true
},
{
"_id": "u2"
},
{
"_id": "u3"
}
],
},
{
_id: "t2",
members: [
{
"_id": "u2",
"leader": true
},
{
"_id": "u4"
}
],
},
{
_id: "t3",
members: [
{
"_id": "u1",
"leader": true
},
{
"_id": "u4"
}
],
},
{
_id: "t4",
members: [
{
"_id": "u2",
"leader": true
}
],
},
],
"users": [
{
"_id": "u1",
"subject": "history"
},
{
"_id": "u2",
"subject": "maths"
},
{
"_id": "u3",
"subject": "geography"
},
{
"_id": "u4",
"subject": "french"
}
]
}
我想要的结果是:
{
"history": ["t1", "t3"],
"maths": ["t2", "t4"]
}
我有一个聚合,可以让我获得每个领导者的_id,然后从那里我可以分阶段获得我想要的结果,方法是首先找到每个领导者的主题,然后再遍历项目并为每个主题分配一个主题基于领导者身份的项目。它可以工作,但是很优雅,我认为它会很慢。在我看来,应该有一些更好的方法来做到这一点,也许像加入吗?
是否有一种巧妙的方法可以从单个MongoDB操作中获得我想要的结果?
这是一个包含我的数据的Mongo游乐场:
https://mongoplayground.net/p/SIJv9-hVNzJ
非常感谢您的帮助。
编辑:我的测试数据令人困惑,因为两个集合中都使用了“ _id”,因此很难解开答案。这是更新后的Mongo Playground,它为每个集合使用不同的键名,并帮助我理解了完美的答案。
答案 0 :(得分:0)
是的,您应该在users._id
上用 $lookup
加入收藏,然后用 $arrayToObject
将值转换为键(在Mongodb 3.4.4中引入)
这是一种可行的方法:
db.teams.aggregate([
{
"$unwind": "$members"
},
{
"$match": {
"members.leader": true
}
},
{
"$lookup": {
"from": "users",
"localField": "members._id",
"foreignField": "_id",
"as": "users"
}
},
{
"$unwind": "$users"
},
{
"$group": {
"_id": "$users.subject",
"team": {
"$push": "$_id"
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[
{
k: "$_id",
v: "$team"
}
]
]
}
}
}
])