For example, if I have a document like this
{
a: 1,
subdoc: {
b: 2,
c: 3
}
}
How can I convert it into a format like this? (without using project
)
{
a: 1,
b: 2,
c: 3
}
For example, if I have a document like this
{
a: 1,
subdoc: {
b: 2,
c: 3
}
}
How can I convert it into a format like this? (without using project
)
{
a: 1,
b: 2,
c: 3
}
You can use MongoDB projection i.e $project
aggregation framework pipeline operators as well. (recommended way). If you don't want to use project
check this link
db.collection.aggregation([{$project{ . . }}]);
Below is the example for your case:
db.collectionName.aggregate
([
{ $project: { a: 1, 'b': '$subdoc.b', 'c': '$subdoc.c'} }
]);
Gives you the output as you expected i.e.
{
"a" : 1,
"b" : 2,
"c" : 3
}
You can use $replaceRoot
with a $addFields
stage as follows:
db.collection.aggregate([
{ "$addFields": { "subdoc.a": "$a" } },
{ "$replaceRoot": { "newRoot": "$subdoc" } }
])
You can do this with the use of $set
and $unset
db.collection.update({},{ $set: { "b": 2, "c": 3 }, $unset: { "subdoc": 1 } })
Of course if there are lots of documents in the collection, then much as above you need to loop the collection documents in order to get the values. MongoDB has no way of referring to a value of a field in an update operation alone:
db.collection.find({ "subdoc": {"$exists": 1 } }).forEach(function(doc) {
var setDoc = {};
for ( var k in doc.subdoc ) {
setDoc[k] = doc.subdoc[k];
}
db.collection.update(
{ "_id": doc._id },
{ "$set": setDoc, "$unset": "subdoc" }
);
})
That also employs some safe usage of $exists
in order to make sure you are selecting documents where the "subdoc" key is actually there.
I guess the easiest way is altering the result after it returns, using map
.
collection.mapFunction = function(el) {
el.b = el.subdoc.b;
el.c = el.subdoc.c
delete(el.subdoc);
return el;
}
...
var result = await collection.aggregate(...).toArray();
result = result.map(collection.mapFunction);
The best way is with $replaceRoot
and $mergeObjects
let pipeline = [
{
"$replaceRoot":{
"newRoot":{
"$mergeObjects":[
{
"a":"$a"
},
"$subdoc"
]
}
}
}
]
db.collection.aggregate(pipeline)