Con MongoDB 3.4 puede usar $objectToArray
y $arrayToObject
con $replaceRoot
para cambiar esto:
db.wish.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$concatArrays": [
[{ "k": "a", "v": "$a" }],
{ "$objectToArray": "$z" }
]
}
}
}}
])
O incluso este largo conjuro sin siquiera especificar el "a"
propiedad:
db.wish.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$reduce": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "r",
"cond": { "$ne": [ "$$r.k", "_id" ] }
}
},
"initialValue": [],
"in": {
"$concatArrays": [
"$$value",
{ "$cond": {
"if": { "$gt": [ "$$this.v", {} ] },
"then": { "$objectToArray": "$$this.v" },
"else": ["$$this"]
}}
]
}
}
}
}
}}
])
Ambos producen:
{ "a" : 1, "b" : 2, "c" : 3 }
El divertido uso de $concatArrays
no debería ser necesario en versiones futuras ya que habrá un $mergeObjects
operador que lo hará un poco más limpio.
Pero básicamente puede hacer lo mismo en el código del cliente de manera bastante simple. Por ejemplo, en JavaScript para el shell:
db.wish.find().map( doc => (
Object.assign({ a: doc.a }, doc.z )
))
O la versión sin el "a"
de nuevo:
db.wish.find().map( doc =>
Object.keys(doc).filter(k => k !== '_id').map(k =>
( typeof(doc[k]) === "object" ) ?
Object.keys(doc[k]).map(i => ({ [i]: doc[k][i] }))
.reduce((acc, curr) => Object.assign(acc,curr),{})
: { [k]: doc[k] }
).reduce((acc,curr) => Object.assign(acc,curr),{})
)
Produce la misma salida
{ "a" : 1, "b" : 2, "c" : 3 }