Given this collection of courses, there is a list of subjects that are composed of objects. Is it possible to create an aggregation to create a new field newSubjects
that maps all subjects by their ids? For example, given this collection how to transform the subjects
entries from :
[
{
_id: ObjectId("623e2f0cb242ee9367eb3c9f"),
subjects: [ { id: '1', name: 'math' }, { id: '2', name: 'physics' } ]
},
{
_id: ObjectId("623e2f17b242ee9367eb3ca0"),
subjects: [ { id: '1', name: 'math' }, { id: '3', name: 'biology' } ]
}
]
into:
{
newSubjects: { '1': { id: '1', name: 'math' }, '2': { id: '2', name: 'physics' } }
}
{
newSubjects: { '1': { id: '1', name: 'math' }, '3': { id: '3', name: 'biology' } }
}
Using JavaScript I could do with this expression:
db.courses.find().forEach(x => print({"newSubjects": Object.fromEntries(new Map(x.subjects.map(s => [s.id, s])))}))
I’m trying to figure out an aggregation to accomplish this but haven’t succeeded with $addField
and $map
yet.
2
Answers
You can try this query:
Only need one aggregate stage to compound the result you want. In this stage you can use a
$map
to iterate for every value and return a new one. This new one will havek
andv
fields.k
field will be the object key (1, 2, 3…)v
field will be the value field (the object with {id:…, name:…})And wrapped by
$arrayToObject
to translatek
andv
to the desired object.Example here
Another option:
Explained:
Map the array with the necessary k,v suitable for arrayToObject to be projected as newSubjects
playground