'MongoDB: nested $group and $push but instead of get an array get a document
I have a couple million of bulky documents with a structure similar to this one (but with way more fields):
{ "class": 3, "type": "A", "color": "r", "filed1": "something", ... }
{ "class": 3, "type": "A", "color": "r", "filed1": "_", ... }
{ "class": 3, "type": "A", "color": "r", "filed1": "45", ... }
{ "class": 3, "type": "A", "color": "g", "filed1": "yt", ... }
{ "class": 3, "type": "B", "color": "b", "filed1": "xx", ... }
{ "class": 1, "type": "A", "color": "r", "filed1": "ds", ... }
{ "class": 1, "type": "A", "color": "r", "filed1": "bb", ... }
{ "class": 1, "type": "A", "color": "r", "filed1": "go", ... }
{ "class": 1, "type": "B", "color": "b", "filed1": "aa", ... }
{ "class": 1, "type": "B", "color": "g", "filed1": "ññ", ... }
And I want to group them by class, then by type and then by color so it looks like this.
{
_id: 3,
A: {
r: [ { field1: "something", ... }, { field1: "_", ... }, { field1: "45", ... } ],
g: [ { field1: "yt", ... } ],
}
B: {
b: [ { field1: "xx", ... } ],
}
}
{
_id: 1,
A: {
r: [ { field1: "ds", ... }, { field1: "bb", ... }, { field1: "go", ... } ]
}
B: {
b: [ { field1: "aa", ... } ],
g: [ { field1: "ññ", ... } ],
}
}
So far I have tried to $group the first level and then "unpack" the array using $arrayToObject.
{
$group: {
"_id": "$class",
data: { $push: { k: "$type", v: { color: "$color", field1: "$field1", ... } } }
}
},
{
$project: {
_id: 1,
data: { $arrayToObject: "$data" }
}
}
But this results in both the undesired field "data" and truncation of the documents.
{
_id: 3,
data: {
A: { "color": "g", "filed1": "yt", ... },
B: { "color": "b", "filed1": "xx", ... }
}
}
{
_id: 1,
data: {
A: { "color": "r", "filed1": "go", ... },
B: { "color": "g", "filed1": "ññ", ... }
}
}
I am trying to avoid using the javascript function forEach because of the size of the collection (about 2 GB) and the low specs of the server, but if you think there is no other way feel free to tell me.
Solution 1:[1]
db.collection.aggregate([
{
$group: {
_id: {
class: "$class",
type: "$type",
color: "$color"
},
v: { $push: { filed1: "$filed1", field2: "$field2" } }
}
},
{
$group: {
_id: {
class: "$_id.class",
type: "$_id.type"
},
docs2: { $push: { k: "$_id.color", v: "$v" } }
}
},
{
$group: {
_id: "$_id.class",
docs3: { $push: { k: "$_id.type", v: { $arrayToObject: "$docs2" } } }
}
},
{
$replaceWith: { $mergeObjects: [ { _id: "$_id" }, { $arrayToObject: "$docs3" } ] }
}
])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | YuTing |
