'Mongo convert embedded document to array
Is there a way to convert a nested document structure into an array? Below is an example:
Input
"experience" : {
"0" : {
"duration" : "3 months",
"end" : "August 2012",
"organization" : {
"0" : {
"name" : "Bank of China",
"profile_url" : "http://www.linkedin.com/company/13801"
}
},
"start" : "June 2012",
"title" : "Intern Analyst"
}
},
Expected Output:
"experience" : [
{
"duration" : "3 months",
"end" : "August 2012",
"organization" : {
"0" : {
"name" : "Bank of China",
"profile_url" : "http://www.linkedin.com/company/13801"
}
},
"start" : "June 2012",
"title" : "Intern Analyst"
}
],
Currently I am using a script to iterate over each element, convert them to an array & finally update the document. But it is taking a lot of time, is there a better way of doing this?
Solution 1:[1]
For mongoDB version >4.2 :
db.doc.aggregate([{ $match: {'experience.0': { $exists: false } } },
{$project:{experience:["$experience.0"]}}, { $merge: { into: "doc", on: "_id" }
])
Note : Here we're merging the updated field/document with existing, but not replacing/updating entire document, default behavior of $merge is merge whenMatched document is found, You can pass other options like replace/keepExisting etc.
Ref: $merge
Solution 2:[2]
See if this query works with your MongoDB version
For MongoDB version 3.2+:
db.doc.aggregate([
{$project:{experience:["$experience.0"]}}
])
MongoDB < 3.2:
db.doc.aggregate([
{$group: {_id:"$_id", experience:{$push:"$experience.0"}}}
])
It should transform your document into:
{
"_id" : ObjectId("56f1b046a65ea8a72c34839c"),
"experience" : [
{
"duration" : "3 months",
"end" : "August 2012",
"organization" : {
"0" : {
"name" : "Bank of China",
"profile_url" : "http://www.linkedin.com/company/13801"
}
},
"start" : "June 2012",
"title" : "Intern Analyst"
}
]
}
A better approach if you want to alter documents in collection permanently using aggregation framework.
Lets assume your collection name is doc
db.doc.aggregate([
{$group: {_id:"$_id", experience:{$push:"$experience.0"}}},
{$out: "doc"}
])
Query above will transform all of your documents in place.
Solution 3:[3]
I am not sure, why aren't there any good answers yet.
It's super easy with aggregation "$set", set is used to add a new field. here you can add a new field with same name into an array. So it will override the older field.
Refer below example:
db.collectionName.aggregate[
// match/other aggregations
{$set: { "experience": ["$experience"] } }
];
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | whoami - fakeFaceTrueSoul |
| Solution 2 | Cerbrus |
| Solution 3 | Ravi Soni |
