MongoDB 聚合中的嵌套分组
Nested grouping in MongoDB aggregation
上下文:
我有一个 MongoDB 满是这样的文档,我想把它们分成一组 json:
[
{
"_id": "615dc97907f597330c510279",
"code": "SDFSDFSDF",
"location": "ABC1",
"week_number": 40,
"year": 2021,
"region": "NA"
},
....
{
"_id": "615dc97907f597330c51027a",
"code": "SDFSGSGR",
"location": "ABC1",
"week_number": 40,
"year": 2021,
"region": "EU"
},
....
{
"_id": "615dc97607f597330c50ff50",
"code": "GGSFHSFS",
"location": "DEF2",
"week_number": 40,
"year": 2021,
"region": "EU",
"audit_result": {
"issues_found": true,
"comment": "comment."
}
}
]
我正在尝试编写一个聚合,它应该 return 并且对象如下:
{
[
"EU": {
2021: {
40: {
"ABC1": {
(All documents for location ABC1 and week 40, year 2021 and region EU)
}
},
39: {
....
}
},
2020: {
....
}
},
"NA": {
....
}
]
}
问题:
我不是 100% 确定怎么做。
我开始按地区对它们进行分组,但我不确定在第一组之后如何进行。
我尝试先按位置对它们进行分组,然后按区域分组,但这似乎也没有像我预期的那样工作。
文档不讨论这样的案例和示例,我发现仅按一两个事物分组,而不是四个。
非常感谢任何见解:)
使用动态值作为字段名通常被认为是反模式,您应该避免这种情况。您可能会给编写和维护查询带来不必要的困难。
不过,您可以在聚合管道中执行以下操作:
$group
最高级:region, year, week_number, location
; $addToSet
将所有 $ROOT
文档分组到一个名为 v
的数组中
$group
在 1 个较粗的级别:region, year, week_number
;创建 k-v 元组,k
是位置,v
是步骤 1 中的 v
。使用 $addToSet
将 k-v 元组分组到名为 v
[ 的数组中=59=]
- 使用
$arrayToObject
将您的 k-v 元组转换为具有动态值的字段,例如
"ABC" : [
{
"_id": "615dc97907f597330c510279",
...
},
...
]
- 基本上在 1 个更粗略的级别重复步骤 2 和 3:
region, year
;创建 k-v 元组,k
是位置,v
是步骤 3 中的 v
。使用 $addToSet
将 k-v 元组分组到名为 v
[ 的数组中=59=]
- 在更粗略的 1 个级别重复步骤 4:
region
$group
无条件地(即 $group
by _id: null
);重复上一步将结果放入名为 v
的单个数组中;使用$arrayToObject
再次转换
$replaceRoot
以获得您的预期结果
这里有一个小提示:当$arrayToObject
像year
和week_number
这样的数字k值时,k值需要事先转换成String。您可以使用 $toString
来实现这一点。
这里是Mongo playground供您参考。
上下文:
我有一个 MongoDB 满是这样的文档,我想把它们分成一组 json:
[
{
"_id": "615dc97907f597330c510279",
"code": "SDFSDFSDF",
"location": "ABC1",
"week_number": 40,
"year": 2021,
"region": "NA"
},
....
{
"_id": "615dc97907f597330c51027a",
"code": "SDFSGSGR",
"location": "ABC1",
"week_number": 40,
"year": 2021,
"region": "EU"
},
....
{
"_id": "615dc97607f597330c50ff50",
"code": "GGSFHSFS",
"location": "DEF2",
"week_number": 40,
"year": 2021,
"region": "EU",
"audit_result": {
"issues_found": true,
"comment": "comment."
}
}
]
我正在尝试编写一个聚合,它应该 return 并且对象如下:
{
[
"EU": {
2021: {
40: {
"ABC1": {
(All documents for location ABC1 and week 40, year 2021 and region EU)
}
},
39: {
....
}
},
2020: {
....
}
},
"NA": {
....
}
]
}
问题:
我不是 100% 确定怎么做。
我开始按地区对它们进行分组,但我不确定在第一组之后如何进行。 我尝试先按位置对它们进行分组,然后按区域分组,但这似乎也没有像我预期的那样工作。
文档不讨论这样的案例和示例,我发现仅按一两个事物分组,而不是四个。
非常感谢任何见解:)
使用动态值作为字段名通常被认为是反模式,您应该避免这种情况。您可能会给编写和维护查询带来不必要的困难。
不过,您可以在聚合管道中执行以下操作:
$group
最高级:region, year, week_number, location
;$addToSet
将所有$ROOT
文档分组到一个名为v
的数组中
$group
在 1 个较粗的级别:region, year, week_number
;创建 k-v 元组,k
是位置,v
是步骤 1 中的v
。使用$addToSet
将 k-v 元组分组到名为v
[ 的数组中=59=]- 使用
$arrayToObject
将您的 k-v 元组转换为具有动态值的字段,例如
"ABC" : [
{
"_id": "615dc97907f597330c510279",
...
},
...
]
- 基本上在 1 个更粗略的级别重复步骤 2 和 3:
region, year
;创建 k-v 元组,k
是位置,v
是步骤 3 中的v
。使用$addToSet
将 k-v 元组分组到名为v
[ 的数组中=59=] - 在更粗略的 1 个级别重复步骤 4:
region
$group
无条件地(即$group
by_id: null
);重复上一步将结果放入名为v
的单个数组中;使用$arrayToObject
再次转换$replaceRoot
以获得您的预期结果
这里有一个小提示:当$arrayToObject
像year
和week_number
这样的数字k值时,k值需要事先转换成String。您可以使用 $toString
来实现这一点。
这里是Mongo playground供您参考。