Zip arrays with MongoDB
Is it possible to archive arrays in a mongo document? I mean the definition of functional programming zip where matching elements are concatenated into tuples.
To be more precise, I would like to start from the mongo doc like this:
{
"A" : ["A1", "A2", "A3"],
"B" : ["B1", "B2", "B3"],
"C" : [100.0, 200.0, 300.0]
}
and as a result we get the following documents:
{"A":"A1","B":"B1","C":100.0},
{"A":"A2","B":"B2","C":200.0},
{"A":"A3","B":"B3","C":300.0},
Ideally, this would use the aggregation framework I already use to get my documents at this point.
source to share
Since MongoDB 3.4, we can use the operator $zip
to zip our arrays.
That being said, we can't get the expected result if you don't know the length of your array.
db.collection.aggregate( [
{ "$project": {
"zipped": {
"$zip": { "inputs": [ "$A", "$B", "$C" ] }
}
}}
])
which produces:
{
"_id" : ObjectId("578f35fb6db61a299a383c5b"),
"zipped" : [
[ "A1", "B1", 100 ],
[ "A2", "B2", 200 ],
[ "A3", "B3", 300 ]
]
}
If we know the number of elements in each sub-array, we can use a variable operator $map
that returns an array of the sub-document.
In an expression, $map
we need to use an operator $arrayElemAt
to set the value of our fields A, B, and C.
db.collection.aggregate( [
{ "$project": {
"zipped": {
"$map": {
"input": {
"$zip": { "inputs": [ "$A", "$B", "$C" ] }
},
"as": "el",
"in": {
"A": { "$arrayElemAt": [ "$$el", 0 ] },
"B": { "$arrayElemAt": [ "$$el", 1 ] },
"C": { "$arrayElemAt": [ "$$el", 2 ] }
}
}
}
}}
] )
which produces:
{
"_id" : ObjectId("578f35fb6db61a299a383c5b"),
"zipped" : [
{
"A" : "A1",
"B" : "B1",
"C" : 100
},
{
"A" : "A2",
"B" : "B2",
"C" : 200
},
{
"A" : "A3",
"B" : "B3",
"C" : 300
}
]
}
source to share