How to convert a list of objects with each object having an array of elements, to an array of objects with the subelement as a property
Instead of first fetching the data from the database in the format you don't want and then converting it to a format you want, you could use aggregation to get the data from MongoDB in the desired format:
db.collection.aggregate([ { $unwind: "$blogs" }, { $project: { "_id": 0, name: 1, blogs: 1, date: { $dateFromString: { dateString: "$blogs.created" } } } }, { $sort: { date: -1 } }, { $project: { date: 0 } }])
Explanation of aggregation pipeline stages used in above query:
$unwind
- deconstructblogs
array to output a separate document with each object in theblogs
array$project
- hide_id
field, showname
andblogs
field and create a new field nameddate
and set its value equal to the fieldcreated
converted to date. (The value of thecreated
field is converted to a date to sort the documents correctly based on the date instead of the date string.)$sort
- sort the documents based ondate
field in descending order (-1 for descending, 1 for ascending), i.e. from the most recent date to older date.$project
- hide thedate
field from the output documents
For details on the above mentioned aggregation pipeline stages, see:
Demo:
This demo shows the above mentioned query in action.
Try with Array.prototype.reduce
. Something like this -
const data = [ { "name": "user1", "blogs": [ { "title": "blog1", "created": "01-01-2020" }, { "title": "blog2", "created": "01-01-2020" } ] }, { "name": "user2", "blogs": [ { "title": "blog3", "created": "01-01-2020" }, { "title": "blog4", "created": "01-01-2020" } ] }];const result = data.reduce((acc, curr) => { const { name, blogs } = curr; const blogArr = blogs.map((blog) => { return { name, blog }; }); Array.prototype.push.apply(acc, blogArr); return acc;}, []);console.log(result);
I would use a feature that MongoDB offers named aggregation.What aggregation lets you do is format your data how you want before you fetch it.
Aggregation works in a pipeline format. You give it a list of commands that will be executed in the order you send it in.
For this case the aggregation pipeline would look like:
[{ $unwind: { path: '$blogs' }}, { $project: { _id: 0, name: 1, blog: '$blogs' }}, { $sort: { "blogs.created": -1 }}]
Commands used in this pipeline:
$unwind - deconstructs an array of items into multiple documents which all contain the original fields of the original documents except for the unwound field which now have a value of all the deconstructed objects in the array.
$project - it lets you format the data however you want, removing fields, adding fields and renaming fields.
$sort - As the name says, it lets you sort the documents, specifying the fields to sort by and the order (ascending or descending).
For more information about aggregation, visit MongoDB's website: