'How to sum values using unwind in MongoDB with Spring Data
When using unwind("items") each item produces a duplicate line. This leads to revenue being counted as many times as there are items.
Example: Someone buys 1 item of A and 1 item of B, resulting in a cummulative value of 10. Unwind now inserts a row for each item, leading to a sum(cummulative) of 20.
I tried grouping the elements directly after unwind but have not managed to get it to work properly.
How can I sum each array element without duplication every other value?
I have this data structure
{
"_id": {
"$binary": "VEE6CsjHPvjzS2JYso7mnQ==",
"$type": "3"
},
"sequentialId": {
"$numberLong": "1"
},
"date": "2022-02-04",
"invoiceTotal": {
"$numberDecimal": "9.85"
},
"vatTotal": {
"$numberDecimal": "0"
},
"vatPercentage": {
"$numberDecimal": "19.00"
},
"invoiceNumber": "1111111",
"type": "ELEKTRONISCH",
"aktivkonto": 2800,
"passivkonto": 5200,
"buyerEmail": "",
"username": "",
"shop": "",
"externalId": "",
"shipped": false,
"actualShippingCost": {
"$numberDecimal": "1"
},
"filename": "",
"isReported": false,
"deliveryCostTotal": {
"$numberDecimal": "4.35"
},
"items": [
{
"lineItemId": "",
"amount": "1",
"sku": "A123123",
"title": "",
"priceTotal": {
"$numberDecimal": "4.50"
},
"vatTotal": {
"$numberDecimal": "0"
},
"hardwareCostPerPiece": {
"$numberDecimal": "0.22"
},
"hardwareCostTotal": {
"$numberDecimal": "0.22"
}
},
{
"lineItemId": "",
"amount": "1",
"sku": "B212312",
"title": "",
"priceTotal": {
"$numberDecimal": "1.00"
},
"vatTotal": {
"$numberDecimal": "0"
},
"hardwareCostPerPiece": {
"$numberDecimal": "0.22"
},
"hardwareCostTotal": {
"$numberDecimal": "0.22"
}
}
],
"packagingCost": {
"$numberDecimal": "0.15"
},
"hasInvoiceSent": false,
"tenant": "you!",
"createdAt": {
"$date": "2022-02-04T15:23:40.716Z"
},
"modifiedAt": {
"$date": "2022-02-04T15:23:40.716Z"
},
"_class": "_.RevenueEntity"
}
and this query
fun sumAllByWeeklyAndTenant(tenant: String): Flux<DashboardRevenue> {
val aggregation = newAggregation(
match(findByTenant(tenant)),
unwind("items"),
group("invoiceNumber")
.sum("items.hardwareCostTotal").`as`("hardwareCostTotal"),
project()
.andExpression("year(createdAt)").`as`("year")
.andExpression("week(createdAt)").`as`("week")
.andInclude(bind("hardwareCostTotal", "items.hardwareCostTotal"))
.andInclude(
"invoiceTotal",
"vatTotal",
"actualShippingCost",
"packagingCost",
"marketplaceFeesTotal",
"tenant"
),
group("year", "week", "tenant")
.sum("invoiceTotal").`as`("umsatz")
.sum("actualShippingCost").`as`("portokosten")
.sum("packagingCost").`as`("verpackung")
.sum("marketplaceFeesTotal").`as`("marketplaceFees")
.sum("hardwareCostTotal").`as`("hardwareCost")
.sum("vatTotal").`as`("vatTotal")
.count().`as`("numberOfInvoices"),
sort(Sort.Direction.DESC, "year", "week"),
limit(8),
sort(Sort.Direction.ASC, "year", "week")
)
return reactiveMongoTemplate
.aggregate(aggregation, "revenue", DashboardRevenue::class.java)
.toFlux()
}
Using the data above the query results in
[
{
"_id": {
"year": 2022,
"month": 2,
"week": 0,
"tenant": "einsupershop"
},
"umsatz": 19.70,
"portokosten": 2,
"verpackung": 0.30,
"marketplaceFees": 3.42,
"hardwareCost": 0.22,
"vatTotal": 0,
"numberOfInvoices": 2
}
]
Where the expected value is "invoiceTotal": { "$numberDecimal": "9.85" }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
