Reputation: 11
I want to retrieve a document from mongodb and then convert it a flat object or flat array.So lets say i am having this document:
{
"_id":"57db3e2269d84bfc06ccecef",
"profileId": {
"_id":"57d838072902f1280324cc8d",
"fname":"name",
"lname":"name2"
},
"subjectId": {
"_id":"57a0d71fb62eaf002e1258c2",
"title":"Some Title
},
"comments": [{
"_id":"57db3f046a8dde181a4cce65",
"text":"fggg"
}],
"type":"post",
"text":"dddddddddddddddddddddd",
"datetime":"2016-09-16T00:34:42.888Z"
}
And I want to convert it like this(lets say i don`t need the ids of profileId and subjectId anymore):
{
"_id":"57db3e2269d84bfc06ccecef",
"fname":"name",
"lname":"name2",
"title":"Some Title,
"comments":[
"text":"fggg"
],
"type":"post",
"text":"dddddddddddddddddddddd",
"datetime":"2016-09-16T00:34:42.888Z"
}
Upvotes: 1
Views: 1344
Reputation: 407
I think that could be done with something like:
let myObj = {};
for(var key in myDocument) {
switch(typeof myDocument[key]) {
case 'object':
if(!Array.isArray(myDocument[key])){
myObj[key] = {};
for(var objKey in myDocument[key]) {
if(objKey !== "_id") {
myObj[key][objKey] = myDocument[key][objKey];
}
}
break;
} else {
let arr = [];
myDocument[key].forEach(function(el) {
if(typeof el == 'object') {
for(var elKey in el) {
if(elKey !== '_id') {
arr.push(el);
}
}
}
});
myObj[key] = arr;
break;
}
default:
myObj[key] = myDocument[key];
}
}
I've tried it and gives me this:
myObj = { _id: '57db3e2269d84bfc06ccecef',
profileId: { fname: 'name', lname: 'name2' },
subjectId: { title: 'Some Title' },
comments: [ { _id: '57db3f046a8dde181a4cce65', text: 'fggg' } ],
type: 'post',
text: 'dddddddddddddddddddddd',
datetime: '2016-09-16T00:34:42.888Z' }
But this answer could be optimized maybe because this is for a very exact approach
Upvotes: 0
Reputation: 1208
There are many viable solutions. Some are more dynamic some quite hardcoded. It depends on the complexity of the problem what is better in the end. As you don't want to include all elements, the simplest way to achieve that is to build this object on your own.
// mngObject is coming from mongoose.
mngObject.fname = mngObject.profileId.fname
// and so on
// At the end
delete mngObject.profileId;
Upvotes: 0
Reputation: 11650
Take a look at MongoDB's Aggregation Framework.
Something like this might do the trick:
db.<collection>.aggregate([
// reformat all except comments
{$project: {
_id: '$_id',
fname: '$profileId.fname',
lname: '$profileId.lname',
title: '$subjectId.title',
comments: '$comments',
type: '$type',
text: '$text',
datetime: '$datetime'
}},
// unwind comments
{$unwind: '$comments'},
// re-formate with comments
{$group: {
_id: '$_id',
fname: {$first: '$fname'},
...
comments: {$push: '$comments.text'}
}}
])
It's possible to accomplish the same thing with just the $unwind
and $group
stages, but I added the $project
stage to demonstrate what it can do.
Or just write a script:
db.<collection>.find(function(err, docs) {
if (err) {
// handle error
}
// reformat docs
var reshapedDocs = [];
docs.forEach(function(doc) {
var reshapedDoc = {};
reshapedDoc.fname = doc.profileId.fname;
// ...
reshapedDoc.comments = [];
doc.comments.forEach(function(comment) {
reshapedDoc.comments.push(comment.text);
});
// ...
reshapedDocs.push(reshapedDoc);
});
});
Upvotes: 1