Mongodb按内部元素分组
Posted
技术标签:
【中文标题】Mongodb按内部元素分组【英文标题】:Mongodb group by inner element 【发布时间】:2021-12-20 00:24:08 【问题描述】:我用一个简单的例子来解释我的 mongodb 集合看起来像这样, [
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 ,
,
]
从集合中,我需要每个用户的级别 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
]
【问题讨论】:
【参考方案1】:$set
:通过将 LevelDetails
转换为键值对来添加新字段 _levelDetails
。
$unwind
:解构_levelDetails
数组。
$group
:根据级别 (_levelDetails.k
) 有条件地按 _levelDetails.v.userId
和 $sum
分组。
$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
])
Sample Mongo Playground
至键值对:
'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"
])
Sample Mongo Playground (To Key-Value Pair)
【讨论】:
以上是关于Mongodb按内部元素分组的主要内容,如果未能解决你的问题,请参考以下文章
Mongodb:按元素分组并根据条件显示子文档计数并按日期对文档进行排序