mongodb - 每个文档级别的聚合 mongodb
问题描述
我有一份这样的文件清单
[{
"_id": "5dbc95f921d7625303fe2369",
"name": "John",
"itemsPurchased": [{
"offer": "o1",
"items": ["p1"]
},{
"offer": "o1",
"items": ["p1"]
},
{
"offer": "o1",
"items": ["p2"]
},
{
"offer": "o2",
"items": ["p1"]
}, {
"offer": "o7",
"items": ["p1"]
}
]
},
{
"_id": "zbc95f921d7625303fe2363",
"name": "Doe",
"itemsPurchased": [{
"offer": "o1",
"items": ["p11"]
},{
"offer": "o1",
"items": ["p11"]
},
{
"offer": "o2",
"items": ["p13"]
},
{
"offer": "o1",
"items": ["p22"]
},
{
"offer": "o2",
"items": ["p11"]
}, {
"offer": "o3",
"items": ["p11"]
}
]
}
]
我正在尝试计算每个客户对独特产品的独特报价,期望结果如下:
[
{
"_id": "5dbc95f921d7625303fe2369",
"name": "John",
"offersAndProducts": {
"o1":2,
"o2":2,
"o3":1
},
{
"_id": "zbc95f921d7625303fe2363",
"name": "Doe",
"offersAndProducts": {
"o1":2,
"o2":1,
"o7":1
}
]
我想对每个文档应用聚合,在对 itemsPurchased 执行 $unwind 后,对项目应用 $group,然后提供以消除重复:
{
"$group" : {
"_id" : {
"item" : {
"$arrayElemAt" : [
"$itemsPurchased.item",
0.0
]
},
"count" : {
"$sum" : 1.0
},
"offer" : "$itemsPurchased.offer"
}
}
}
然后,
{
"$group" : {
"_id" : "$_id.offer",
"count" : {
"$sum" : 1.0
}
}
}
这为所有文档提供了一系列产品和优惠:
[
{o1:4,o2:3,o3:1,o7:1}
]
但我需要它在文档级别。尝试过$addFeild
,但是$unwind
和 $match 运算符给出了无效错误。
还有其他方法可以实现吗?
解决方案
一般来说,它是$unwind
一个数组的反模式,然后$group
是原始的_id
,因为大多数操作都可以在一个阶段直接在数组上完成。这是这样一个阶段的样子:
{$addFields:{
offers:{$arrayToObject:{
$map:{
input:{$setUnion:"$itemsPurchased.offer"},
as:"o",
in:[
"$$o",
{$size:{$setUnion:{$let:{
vars:{items:{$filter:{
input:"$itemsPurchased",
cond:{$eq:["$$this.offer","$$o"]}
}}},
in:{$reduce:{
input:"$$items",
initialValue:[],
in:{$concatArrays:["$$value","$$items.items"]}
}}
}}}
}]
}
}}
}}
这样做是创建一个数组,其中每个元素都是一个双元素数组(这是一种$arrayToObject
可以转换为第一个元素是键名,第二个是值的对象的语法),输入是一组唯一的报价,对于每个我们累积一个产品数组,去掉重复项(用$setUnion
),然后得到结果的大小。这对您的输入产生的结果是:
"offers" : {
"o1" : 2,
"o2" : 2,
"o3" : 1
}
推荐阅读
- excel - 剪切行并粘贴到上面的一个单元格中 - 复制和粘贴区域的运行时间错误与重叠不匹配
- c# - 使用 jquery 或 javascript 在 GridView 的 TemplateField 中查找控件
- .net - 如何通过 Powershell 更新 AppDynamics .net 代理?
- android - 如何解析和显示响应 Okhttp 的代码?
- dart - Flutter - 有没有办法只使用 IconButton(不创建应用栏)来打开抽屉?
- unity3d - 使用 Unity Physics 将球持续反弹到相同的高度
- python - 如何将用户定义的行函数应用于加载的数组的所有行?
- amazon-web-services - 使用 CNAME 的外部站点,用于托管在 AWS 上的站点
- android - 当我使用 LinearLayout 而不是 CardView 作为父 XML 布局时,RecyclerView 仅显示 1 个项目
- xml - .gitignore 中的 .idea/compiler.xml?