I have a collection of documents books
:
{
title: "My book",
authors: [{id: 1, date: "2023-12-20"},{id: 2, date: "2023-12-21"}],
authorsDetails: [{id: 2, name:"Author 2", age: 25}, {id: 1, name: "Author 1", age: 38}],
}
I need to do an aggregation and the result must return the following result:
{
title: "My book",
authors: [{id: 1, date: "2023-12-20", name: "Author 1"},{id: 2, date: "2023-12-21", name: "Author 2"}],
}
Basically I need to add some informations from authorsDetails
to authors
. In this case only the name.
NOTE: The two arrays are not necessary sorted in the same way.
I tried an $addFields
pipe + $map
but it is not enough. I tried this:
const pipeline = [
//...
{
$addFields: {
indices: { $range: [0, { $size: '$authors' }] },
},
},
{
$addFields: {
admins: {
$map: {
input: '$indices',
as: 'index',
in: {
detail: { $arrayElemAt: ['$authorsDetails', '$$index'] },
author: { $arrayElemAt: ['$authors', '$$index'] },
},
},
},
},
},
//...
]
This works only if the arrays are sorted in the same way. Also I need to do another map to fix this as I expect.
Do you have any idea on how to do this?
2
Answers
Under the assumption that the ids in 2 arrays are 1 to 1 correspondence(i.e. the id in author will only map to 1 entry in authorDetails Array and there is no missing/duplicate entry), we can first
$sortArray
to align the entries. Then use$zip
and$mergeObjects
to combine the array entries.Mongo Playground
Here is a simple approach where you
$concatArrays
first , then you can$unwind
the new array and$group
back together based onauthors.id
and then$mergeObjects
within that$group
stage. I had to do another$group
stage to keep hold of thattitle
but it does the job. Hopefully someone sees a more efficient way so that it can be improved.Key point here is you don’t need to rely on any sorting.
See HERE for a working example.