I tried to use aggregate and lookup but look like I cannot keep role
in the members
item. Any idea how to resolve it?
db.groups.insertMany([
{
title: 'Hi',
members: [
{
userId: ObjectId('62589515f239750e7e44b958'),
role: 'Admin'
},
{
userId: ObjectId('655f634c632d0c23b9d455de'),
role: 'Member'
}
]
}
])
and
db.users.insertMany([
{
_id: ObjectId('62589515f239750e7e44b958'),
name: 'A',
},
{
_id: ObjectId('655f634c632d0c23b9d455de'),
name: 'B',
}
])
How do we can have a result like this by using aggregate, many thanks:
{
title: 'Hi',
members: [
{
user: {
_id: ObjectId('62589515f239750e7e44b958'),
name: 'A',
},
role: 'Admin'
},
{
user: {
_id: ObjectId('655f634c632d0c23b9d455de'),
name: 'B',
},
role: 'Member'
},
]
}
2
Answers
$unwind
the members and perform$lookup
. Wrangle the object a bit and$group
to reform the object.Mongo Playground
The issue with the lookup is that if you insert the new field into an existing array it replaces that array, rather than adding the result to each object in the array. The Mongo docs provide a similar example with
$lookup
and$mergeObjects
. The key to using it effectively in your case is to$unwind
themembers
first. And at the end, un-unwind (rewind? windup?) the objects and add themembers.user
to a single array.Mongo Playground
PS. Needs a more elegant solution to choose all the "other" fields in the final
$group
. Right now, "title" is the only one so it’s fine but maybe something with a $project would work better for those cases.For the curious, the difference between this and Ray’s answer is that I lookup into the
members
object rather than at the root level. If there were many fields in each object of members, then this pipeline doesn’t requireset
ting each of the other fields.