Unwind dictionary values in mongodb aggregation framework
Asked Answered
H

1

6

I need to create some plots from single documents existing in mongodb. I can only use the mongodb aggregation framework (so for example I cannot just pull the documents into python and work with it there). I am using the query builder of metabase, so I am limited from this regard.

In order to do this, I am first using some $match queries in order to identify the documents that I need to look at (these are predefined and static). After the $match stage, I am left with one document (this is ok) with the following structure.

{
 "id": 1,
 "locs": {
    "a":1,
    "b":2, 
    "c":3
  }
}

I need to change this structure to something like this:

[{"a":1}, {"b":2}, {"c":3"}]

or any other form that would allow me to create pie charts out of the structure.

Thanks!

Historiography answered 21/11, 2018 at 16:4 Comment(0)
G
7

You can convert locs object to array using $objectToArray. Now $unwind the locs array to split into multiple documents. Use $group with $push accumulator to make the split data again into k and v format. And finally use $replaceRoot with the final data field to move it to $$ROOT position.

db.collection.aggregate([
  { "$project": { "data": { "$objectToArray": "$locs" }}},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "data": { "$push": { "k": "$data.k", "v": "$data.v" }}
  }},
  { "$project": {
    "data": { "$arrayToObject": "$data" }
  }},
  { "$replaceRoot": { "newRoot": "$data" }}
])
Gaby answered 21/11, 2018 at 16:54 Comment(3)
You rock! It worked almost perfectly, I just needed to add a { "$unwind": "$data" } before the $replaceRoot step.Historiography
Can this be done in the aggregation pipeline without $objectToArray / $arrayToObject (prior to 3.4.4)?Boater
@Boater No. It would be better if you update your mongo version because new versions are introduced for comfortablenessGaby

© 2022 - 2024 — McMap. All rights reserved.