MongoDB - 按内部元素分组
MongoDB - Group by inner element
我用一个简单的例子来解释看我的 MongoDB collection 看起来像这样:
[
{
pid: erwer,
qty: 3,
LevelDetails: {
level1: { userId: 1, amount: 10 },
level2: { userId: 2, amount: 20 },
level3: { userId: 3, amount: 13 },
}
},
{
pid: qwsdfg,
qty: 1,
LevelDetails: {
level1: { userId: 1, amount: 10 },
level2: { userId: 4, amount: 20 },
level3: { userId: 3, amount: 13 },
}
},
]
从collection开始,我需要每个用户的级别 1、级别 2 和级别 3 的总和。
查询结果应该是这样的:
[
{ userId1: { TotalLevel1Amount: 20, TotalLevel2Amount: 0, TotalLevel3Amount: 0 } },
{ userId2: { TotalLevel1Amount: 0, TotalLevel2Amount: 20, TotalLevel3Amount: 0 } },
{ userId3: { TotalLevel1Amount: 0, TotalLevel2Amount: 0, TotalLevel3Amount: 26 } },
{ userId4: { TotalLevel1Amount: 0, TotalLevel2Amount: 20, TotalLevel3Amount: 0 } }
]
$set
:通过将 LevelDetails
转换为键值对来添加新字段 _levelDetails
。
$unwind
: 解构_levelDetails
数组。
$group
:根据_levelDetails.v.userId
和$sum
有条件地根据级别(_levelDetails.k
)进行分组。
$project
: 格式化显示文档。
$sort
(可选):按 userID
升序排序。
db.collection.aggregate([
{
$set: {
_levelDetails: {
$objectToArray: "$LevelDetails"
}
}
},
{
$unwind: "$_levelDetails"
},
{
$group: {
_id: "$_levelDetails.v.userId",
"TotalLevel1Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level1"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel2Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level2"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel3Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level3"
]
},
"$_levelDetails.v.amount",
0
]
}
}
}
},
{
$project: {
_id: 0,
userId: "$_id",
TotalLevel1Amount: 1,
TotalLevel2Amount: 1,
TotalLevel3Amount: 1
}
},
{
$sort: {
userId: 1
}
}
])
To Key-Value Pair: { 'userId': { // Result } }
步骤 1 到 3 与前面的解决方案相同。
$sort
(可选):按 _id
升序排序。
$project
:显示带有 array
字段的文档(具有属性 k
和 v
)。
$replaceRoot
:将整个文档替换为键(userId
)和值(结果)。
db.collection.aggregate([
{
$set: {
_levelDetails: {
$objectToArray: "$LevelDetails"
}
}
},
{
$unwind: "$_levelDetails"
},
{
$group: {
_id: "$_levelDetails.v.userId",
"TotalLevel1Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level1"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel2Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level2"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel3Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level3"
]
},
"$_levelDetails.v.amount",
0
]
}
}
}
},
{
$sort: {
_id: 1
}
},
{
$project: {
array: [
{
k: {
$toString: "$_id"
},
v: {
TotalLevel1Amount: "$TotalLevel1Amount",
TotalLevel2Amount: "$TotalLevel2Amount",
TotalLevel3Amount: "$TotalLevel3Amount"
}
}
]
}
},
{
"$replaceRoot": {
newRoot: {
$arrayToObject: "$array"
}
}
}
])
我用一个简单的例子来解释看我的 MongoDB collection 看起来像这样:
[
{
pid: erwer,
qty: 3,
LevelDetails: {
level1: { userId: 1, amount: 10 },
level2: { userId: 2, amount: 20 },
level3: { userId: 3, amount: 13 },
}
},
{
pid: qwsdfg,
qty: 1,
LevelDetails: {
level1: { userId: 1, amount: 10 },
level2: { userId: 4, amount: 20 },
level3: { userId: 3, amount: 13 },
}
},
]
从collection开始,我需要每个用户的级别 1、级别 2 和级别 3 的总和。
查询结果应该是这样的:
[
{ userId1: { TotalLevel1Amount: 20, TotalLevel2Amount: 0, TotalLevel3Amount: 0 } },
{ userId2: { TotalLevel1Amount: 0, TotalLevel2Amount: 20, TotalLevel3Amount: 0 } },
{ userId3: { TotalLevel1Amount: 0, TotalLevel2Amount: 0, TotalLevel3Amount: 26 } },
{ userId4: { TotalLevel1Amount: 0, TotalLevel2Amount: 20, TotalLevel3Amount: 0 } }
]
$set
:通过将LevelDetails
转换为键值对来添加新字段_levelDetails
。$unwind
: 解构_levelDetails
数组。$group
:根据_levelDetails.v.userId
和$sum
有条件地根据级别(_levelDetails.k
)进行分组。$project
: 格式化显示文档。$sort
(可选):按userID
升序排序。
db.collection.aggregate([
{
$set: {
_levelDetails: {
$objectToArray: "$LevelDetails"
}
}
},
{
$unwind: "$_levelDetails"
},
{
$group: {
_id: "$_levelDetails.v.userId",
"TotalLevel1Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level1"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel2Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level2"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel3Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level3"
]
},
"$_levelDetails.v.amount",
0
]
}
}
}
},
{
$project: {
_id: 0,
userId: "$_id",
TotalLevel1Amount: 1,
TotalLevel2Amount: 1,
TotalLevel3Amount: 1
}
},
{
$sort: {
userId: 1
}
}
])
To Key-Value Pair:
{ 'userId': { // Result } }
步骤 1 到 3 与前面的解决方案相同。
$sort
(可选):按_id
升序排序。$project
:显示带有array
字段的文档(具有属性k
和v
)。$replaceRoot
:将整个文档替换为键(userId
)和值(结果)。
db.collection.aggregate([
{
$set: {
_levelDetails: {
$objectToArray: "$LevelDetails"
}
}
},
{
$unwind: "$_levelDetails"
},
{
$group: {
_id: "$_levelDetails.v.userId",
"TotalLevel1Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level1"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel2Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level2"
]
},
"$_levelDetails.v.amount",
0
]
}
},
"TotalLevel3Amount": {
$sum: {
$cond: [
{
"$eq": [
"$_levelDetails.k",
"level3"
]
},
"$_levelDetails.v.amount",
0
]
}
}
}
},
{
$sort: {
_id: 1
}
},
{
$project: {
array: [
{
k: {
$toString: "$_id"
},
v: {
TotalLevel1Amount: "$TotalLevel1Amount",
TotalLevel2Amount: "$TotalLevel2Amount",
TotalLevel3Amount: "$TotalLevel3Amount"
}
}
]
}
},
{
"$replaceRoot": {
newRoot: {
$arrayToObject: "$array"
}
}
}
])