Arrays 如何按多个字段对子文档数组进行分组?
我已经花了一天的大部分时间在这上面,现在已经没有主意了。这是我的收藏:Arrays 如何按多个字段对子文档数组进行分组?,arrays,mongodb,aggregation-framework,aggregate,Arrays,Mongodb,Aggregation Framework,Aggregate,我已经花了一天的大部分时间在这上面,现在已经没有主意了。这是我的收藏: [ { "_id": "ID_XXX", "logs": [ { "lead_id": 123, "list_id": "list_44", "order_id": "order_1"
[
{
"_id": "ID_XXX",
"logs": [
{
"lead_id": 123,
"list_id": "list_44",
"order_id": "order_1"
},
{
"lead_id": 124,
"list_id": "list_44",
"order_id": "order_2"
}
]
},
{
"_id": "ID_YYY",
"logs": [
{
"lead_id": 125,
"list_id": "list_44",
"order_id": "order_2"
},
{
"lead_id": 126,
"list_id": "list_44",
"order_id": "order_2"
},
{
"lead_id": 127,
"list_id": "list_44",
"order_id": "order_3"
},
{
"lead_id": 128,
"list_id": "list_66",
"order_id": "order_3"
}
]
}
]
我只是想获取list\u id
和order\u id
的计数,同时保留它们所在文档的\u id
。这是我想要的输出:
[
{
"_id": "ID_XXX",
"counts": [
{
"lists": {"list_44": 2},
},
{
"orders": {"order_1": 1, "order_2": 1}
}
]
},
{
"_id": "ID_YYY",
"counts": [
{
"lists": {"list_44": 3, "list_66": 1},
},
{
"orders": {"order_2": 2, "order_3": 2}
}
]
}
]
我尝试了太多的聚合变体,无法在此列出,但最新的是:
db.collection.aggregate([
{
$unwind: "$logs"
},
{
$group: {
_id: "$_id",
lists: {
$push: "$logs.list_id"
},
orders: {
$push: "$logs.order_id"
}
}
}
])
这并没有给我想要的。谁能给我指出正确的方向吗?这里是操场链接:
要迭代$reduce
,请使用日志的循环
,$objectToArray
和$concatarray
中的初始值,将$reduce
对象转换为k(键)v(值)格式的数组日志
- 上面的
将结果减少为输入,并从$filter
日志中筛选所需字段
解构$unwind
数组日志
由$group
和\u id
记录对象并使用
$sum
按$group
分组,如果\u id
为记录,则生成
数组。k列表
并以k和v格式返回,否则返回列表id
,与$$REMOVE
相同,基于订单
生成订单数组订单id
使用$arrayToObject$addFields
订单`数组相同将
数组从k和v格式转换为对象格式,与列表
这很有效,谢谢。但是考虑到这种聚合的相对复杂性,您是否建议我将原始数据拉入代码中,并在JS中执行此操作,而不是聚合它?我只是想知道你认为什么更有效。这只是一个逻辑,你可以用你的客户端语言来做,它比查询更有效,如果你真的想在聚合中做,那么试试操作符,你可以在这个函数中做JS代码。明白了。在客户端执行此操作时,我担心这些日志可能包含数十万条条目,而且由于我的数据库与我的节点应用程序不在同一台服务器上,我不想将所有数据下载到我的应用程序中来处理它。无论哪种方式,都要感谢你的洞察力。
db.collection.aggregate([
{
$addFields: {
logs: {
$filter: {
input: {
$reduce: {
input: "$logs",
initialValue: [],
in: { $concatArrays: ["$$value", { $objectToArray: "$$this" }] }
}
},
cond: { $in: ["$$this.k", ["list_id", "order_id"]] }
}
}
}
},
{ $unwind: "$logs" },
{
$group: {
_id: {
_id: "$_id",
logs: "$logs"
},
counts: { $sum: 1 }
}
},
{
$group: {
_id: "$_id._id",
lists: {
$push: {
$cond: [
{ $eq: ["$_id.logs.k", "list_id"] },
{
k: "$_id.logs.v",
v: "$counts"
},
"$$REMOVE"
]
}
},
orders: {
$push: {
$cond: [
{ $eq: ["$_id.logs.k", "order_id"] },
{
k: "$_id.logs.v",
v: "$counts"
},
"$$REMOVE"
]
}
}
}
},
{
$addFields: {
lists: { $arrayToObject: "$lists" },
orders: { $arrayToObject: "$orders" }
}
}
])