我使用 MongoDB 版本 7。我存储付款数据以及订单和买家信息。我在一个包含订单和买家信息的集合中有一些付款,我按订单 ID 将其分组到下一个 JSON 结果:
{
"incomeCash": [
{
"_id": "64d5fe21fb5b6271ce7934a1",
"buyer": {
"title": "buyer1",
"key": "64234a2711d053037a0362d1"
},
"key": "64d5fe21fb5b6271ce7934a1", //order 1 key
"title": "ORDER 1",
"payments": [
{
"date": "2023-07-15T00:00:00.000Z",
"amount": "1.01"
}
],
"total": "1.01",
"direction": "in"
},
{
"_id": "6451db5cd001097cb1f27651",
"buyer": {
"title": "buyer1",
"key": "64234a2711d053037a0362d1"
},
"key": "6451db5cd001097cb1f27651", //order 2 key
"title": "ORDER 2",
"payments": [
{
"date": "2023-05-08T00:00:00.000Z",
"amount": "1.01"
},
{
"date": "2023-05-18T00:00:00.000Z",
"amount": "2.02"
},
{
"date": "2023-07-15T00:00:00.000Z",
"amount": "3.03"
}
],
"total": "6.06",
"direction": "in"
}
]
}
所以我的问题是如何按
buyer.key
按日期汇总付款的所有订单进行分组,我要获取下一个 JSON 样式:
[
{
"_id": "64234a2711d053037a0362d1",
"key": "64234a2711d053037a0362d1", //buyer key
"title": "buyer 1",
"subLevels": [
{
"key": "64d5fe21fb5b6271ce7934a1", //order 1 key
"title": "ORDER 1",
"payments": [
{
"date": "2023-07-15T00:00:00.000Z",
"amount": "1.01"
}
],
"total": "1.01",
"direction": "in"
},
{
"key": "6451db5cd001097cb1f27651", //order 2 key
"title": "ORDER 2",
"payments": [
{
"date": "2023-05-08T00:00:00.000Z",
"amount": "1.01"
},
{
"date": "2023-05-18T00:00:00.000Z",
"amount": "2.02"
},
{
"date": "2023-07-15T00:00:00.000Z",
"amount": "3.03"
}
],
"total": "6.06",
"direction": "in"
}
],
"total": 7.07,
"payments": [
{
"date": "2023-05-08T00:00:00.000Z",
"amount": "1.01"
},
{
"date": "2023-05-18T00:00:00.000Z",
"amount": "2.02"
},
{
"date": "2023-07-15T00:00:00.000Z", //group by date
"amount": "4.04" //sum by date
}
]
}
]
附注所有金额和总计均为十进制类型,目前我尝试将
$group
与 $accumulator
和函数一起使用,但并非所有金额都正确求和,例如:
{
"date": "2023-05-08T00:00:00.000Z",
"amount": "1.01"
},
{
"date": "2023-05-18T00:00:00.000Z",
"amount": "2.02"
},
{
"date": "2023-07-15T00:00:00.000Z",
"amount": "NumberDecimal(\"1.01\")NumberDecimal(\"3.03\")"
}
也许还有另一种按日期支付金额的变体,没有函数和带有累加器的组?
认为这是一个复杂的查询,需要多次展开和分组文档。
$unwind
- 将 payments
数组解构为多个文档。
$group
- 按 buyer.key
和 payments.date
分组以执行求和。并将原始文件保留在root
字段中。
unwind
- 将 root
数组解构为多个文档。
$group
- 按 root._id
分组,以便输出文档应与原始文档类似。
$group
- 按 buyer.key
分组。
$set
- 按 subLevels
字段对 payments
和 date
数组中的元素进行排序。特殊情况是在排序之前需要额外的步骤从 payments
数组中删除重复元素。
db.incomeCash.aggregate([
{
$unwind: "$payments"
},
{
$group: {
_id: {
buyerKey: "$buyer.key",
date: {
$toDate: "$payments.date"
}
},
amount: {
$sum: {
$toDecimal: "$payments.amount"
}
},
root: {
$push: "$$ROOT"
}
}
},
{
$unwind: "$root"
},
{
$group: {
_id: "$root._id",
buyer: {
$first: "$root.buyer"
},
key: {
$first: "$root.key"
},
title: {
$first: "$root.title"
},
payments: {
$push: "$root.payments"
},
sumPayments: {
$addToSet: {
date: "$_id.date",
amount: "$amount"
}
},
total: {
$first: "$root.total"
},
direction: {
$first: "$root.direction"
}
}
},
{
$group: {
_id: "$buyer.key",
title: {
$first: "$buyer.title"
},
subLevels: {
$addToSet: {
key: "$key",
title: "$title",
payments: "$payments",
total: "$total",
direction: "$direction"
}
},
total: {
$sum: {
$toDecimal: "$total"
}
},
payments: {
$push: "$sumPayments"
}
}
},
{
$set: {
subLevels: {
$sortArray: {
input: "$subLevels",
sortBy: {
"payment.date": 1
}
}
},
payments: {
$sortArray: {
input: {
$reduce: {
input: "$payments",
initialValue: [],
in: {
$let: {
vars: {
elem: {
$concatArrays: [
"$$this",
"$$value"
]
}
},
in: {
$setUnion: "$$elem"
}
}
}
}
},
sortBy: {
date: 1
}
}
}
}
}
])