My invoices
collection looks something like this:
[
{
inv_name: "Client 1",
inv_date: 2022-12-20T05:09:09.803Z,
inv_ready: false,
inv_payments: [
{
id: "123",
pay_amount: 32.45
},
{
id: "456",
pay_amount: 55.60
}
]
},
{
inv_name: "Client 2",
inv_date: 2022-12-19T05:09:09.803Z,
inv_ready: true,
inv_payments: [
{
id: "459",
pay_amount: 67.45
},
{
id: "556",
pay_amount: 30.60
}
]
}
]
I know how to create an array of just the sub docs using $project
and $unwind
. The goal is to just add some data from the parent document to each object like this.
[
{
"client": "Client 1",
"pay_amount": 32.45,
"pay_date": "123"
},
{
"client": "Client 1",
"pay_amount": 55.6,
"pay_date": "456"
},
{
"client": "Client 2",
"pay_amount": 67.45,
"pay_date": "459"
},
{
"client": "Client 2",
"pay_amount": 30.6,
"pay_date": "556"
}
]
Here is what I tried:
db.invoices.aggregate([
{
"$project": {
_id: 0,
"inv_payments": {
$reduce: {
input: "$inv_payments",
initialValue: [],
in: {
$concatArrays: [
[
{
client: "$this.name",
pay_id: "$$this.id",
pay_amount: "$$this.pay_amount"
}
],
"$inv_payments"
]
}
}
}
}
},
{
$unwind: "$inv_payments"
},
{
$replaceRoot: {
newRoot: "$inv_payments"
}
}
])
I think I am close. I am not sure where the bug is. Any ideas would be greatly appreciated!
CodePudding user response:
Besides the typo error mentioned in the comment, the way you used the $reduce
operator is incorrect. You didn't work with the accumulator variable ($$value
).
Rather than using $reduce
, use the $map
operator which is simpler in your scenario:
Solution 1: $map
{
"$project": {
_id: 0,
"inv_payments": {
$map: {
input: "$inv_payments",
in: {
client: "$inv_name",
pay_date: "$$this.id",
pay_amount: "$$this.pay_amount"
}
}
}
}
}
Demo ($map
) @ Mongo Playground
Solution 2: $reduce
For $reduce
operator, your query should be:
{
"$project": {
_id: 0,
"inv_payments": {
$reduce: {
input: "$inv_payments",
initialValue: [],
in: {
$concatArrays: [
[
{
client: "$inv_name",
pay_date: "$$this.id",
pay_amount: "$$this.pay_amount"
}
],
"$$value"
]
}
}
}
}
}