[英]How to group an array of subdocuments by multiple fields?
I have spent the better part of the day on this and am now out of ideas.我花了一天的大部分时间在这上面,现在没有想法了。 Here is my collection:这是我的收藏:
[
{
"_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"
}
]
}
]
I'm just trying to get the counts for list_id
and order_id
while preserving the _id
of the document they are in. Here is my desired output:我只是想获取list_id
和order_id
的计数,同时保留它们所在文档的_id
。这是我想要的 output:
[
{
"_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}
}
]
}
]
I have tried way too many aggregate variations to list here, but the latest is this:我尝试了太多的聚合变体,无法在此处列出,但最新的是:
db.collection.aggregate([
{
$unwind: "$logs"
},
{
$group: {
_id: "$_id",
lists: {
$push: "$logs.list_id"
},
orders: {
$push: "$logs.order_id"
}
}
}
])
Which does not give me what I want.这并没有给我想要的东西。 Can anyone point me in the right direction?谁能指出我正确的方向? Here is the playground link: https://mongoplayground.net/p/f-jk7lbSrJ0这是操场链接: https://mongoplayground.net/p/f-jk7lbSrJ0
$reduce
to iterate loop of logs
, convert logs
object to array in k(key) v(value) format using $objectToArray
, $concatArrays
with initialValue in $reduce
, $reduce
迭代logs
循环,使用$objectToArray
objectToArray 将logs
object 转换为 k(key) v(value) 格式的数组, $concatArrays
使用$reduce
reduce 中的 initialValue,$filter
above reduce result as input and filter required fields from logs
上面的$filter
将结果减少为输入并从logs
中过滤所需字段$unwind
deconstruct logs
array $unwind
解构logs
数组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
by _id
and logs
object and get the total count using $sum
$group
by _id
并logs
object 并使用$sum
获取总数 {
$group: {
_id: {
_id: "$_id",
logs: "$logs"
},
counts: { $sum: 1 }
}
},
$group
by _id
and make lists
array if logs.k
is list_id
and return in k and v format otherwise $$REMOVE
, same as for orders
make an array of order on the base of order_id
$group
by _id
如果logs.k
是list_id
则创建lists
数组,否则返回 k 和 v 格式$$REMOVE
,与订单相同,在order_id
的基础上创建orders
数组$addFields
to convert lists
array from k and v format to object format using $arrayToObject and same as for
orders` array $addFields
将lists
数组从 k 和 v 格式转换为 object 格式,与订单数组and same as for
{
$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" }
}
}
])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.