considering the following document
"logs": {
"events": {
"type": "call_action",
"attributes": [
{
"key": "module",
"value": "module1"
},
{
"key": "data",
"value": "data_value_module_1"
},
{
"key": "module",
"value": "module2"
},
{
"key": "data",
"value": "data_value_module_2"
}
]
}
},
I am trying to use $arraytoObject to convert key and value
$project: {
"attributes": {
$arrayToObject: {
$map: {
"input": "$logs.events.attributes",
"as": "el",
"in": {
"k": "$$el.key",
"v": "$$el"
}
}
}
}
}
but it overwrite duplicated keys as module
and data
.
How can I use a kind of $unwind or something like that?
The result should be like that
[
{
"logs": {
"events": {
"type": "call_action",
"attributes": {
"module": "module1"
"value": "data_value_module_1"
}
}
}
},
{
"logs": {
"events": {
"type": "call_action",
"attributes": {
"module": "module2"
"value": "data_value_module_2"
}
}
}
}
]
Thank you
CodePudding user response:
Based on this answer, one option is:
db.collection.aggregate([
{$set: {
"logs.events.attributes": {
$reduce: {
input: "$logs.events.attributes",
initialValue: [],
in: {
$concatArrays: [
"$$value",
[
{
k: "$$this.key",
v: "$$this.value",
mod: {$mod: [{$size: "$$value"}, 2]}
}
]
]
}
}
}
}
},
{$project: {
_id: 0,
type: "$logs.events.type",
firstEvent: {
$filter: {
input: "$logs.events.attributes",
cond: {$eq: ["$$this.mod", 0]}
}
},
secondEvent: {
$filter: {
input: "$logs.events.attributes",
cond: {$eq: ["$$this.mod", 1]}
}
}
}
},
{$project: {
"logs.events": {
type: "$type",
attributes: {$zip: {inputs: ["$firstEvent", "$secondEvent"]}}
}
}
},
{$unwind: "$logs.events.attributes"},
{$set: {
"logs.events.attributes": {
$map: {
input: "$logs.events.attributes",
in: {k: "$$this.k", v: "$$this.v"}}
}
}
},
{$set: {"logs.events.attributes": {$arrayToObject: $logs.events.attributes"}}}
])
See how it works on the playground example
Or with a small variation (I generally prefer not to $unwind
and $group
again, but in this case it seems reasonable):
db.collection.aggregate([
{$set: {
"logs.events.attributes": {
$reduce: {input: "$logs.events.attributes",
initialValue: [],
in: {$concatArrays: [
"$$value",
[
{
k: "$$this.key",
v: "$$this.value",
group: {$floor: [{$divide: [{$size: "$$value"}, 2]}]}
}
]
]
}
}
}
}
},
{$unwind: "$logs.events.attributes"},
{$group: {
_id: "$logs.events.attributes.group",
data: {$push: {k: "$logs.events.attributes.k", v: "$logs.events.attributes.v"}},
type: {$first: "$logs.events.type"}
}
},
{$project: {_id: 0, "logs.events": {attributes: {$arrayToObject: "$data" }, type: "$type"}}}
])
See how it works on the playground example - simplified