It is not possible to do this using single update query in MongoDB 3.4,
1) You can do 2 queries first find and second update in loop, You can execute in mongo shell or any MongoDB editor:
find() query to project require field and loop the result
for loop the grades array
- check if condition the grades element is array then concat otherwise return same
update() query to update new grades array
db.getCollection('grades').find({}, { grades: 1 }).forEach(function (doc) {
var grades = [];
for(var i = 0; i < doc.grades.length; i++) {
if (Array.isArray(doc.grades[i])) {
grades = grades.concat(doc.grades[i]);
}
else {
grades.push(doc.grades[i]);
}
}
// update
db.getCollection('grades').update(
{ _id: doc._id },
{ $set: { grades: grades } }
)
})
2) you can try aggregation query and export updated results in the new collection using single query,
$reduce to iterate loop of grades array
$type to get data type of the element
$concatArrays to concat multiple arrays
$cond check condition if element type is array then concat directly both arrays otherwise concat with array into array
$out to export collection in new collection
db.collection.aggregate([
{
$addFields: {
grades: {
$reduce: {
input: "$grades",
initialValue: [],
in: {
$cond: [
{ $eq: [{ $type: "$$this" }, "array"] },
{ $concatArrays: ["$$value", "$$this"] },
{ $concatArrays: ["$$value", ["$$this"]] }
]
}
}
}
}
},
{ $out: "collection name" }
])
Playground
db.collection.updateMany({},
[{
$set: {
grades: {
$reduce: {
input: "$grades",
initialValue: [],
in: {
$cond: [
{ $eq: [{ $type: "$$this" }, "array"] },
{ $concatArrays: ["$$value", "$$this"] },
{ $concatArrays: ["$$value", ["$$this"]] }
]
}
}
}
}
}]
)
Playground