We have a bunch of products in a database with two types of monetary values attached to each. Each object has a manufacturer, a range and a description, and each object can have a monthly rental amount (for rental agreements), a monthly payment amount (for finance agreements) or both.
An example object would be:
{
"manufacturer": "Manufacturer A",
"range": "Range A",
"description": "Product Description",
"rentals": {
"initialRental": 1111.05,
"monthlyRental": 123.45,
"termMonths": 24
},
"payments": {
"deposit": 592.56,
"monthlyPayment": 98.76,
"finalPayment": 296.28,
"termMonths": 36
}
}
There can often be more than one object for a given manufacturer and range.
I'm looking for an aggregation pipeline that will return a list of the lowest monthly rental and the lowest monthly payment for each distinct manufacturer/range pair, but my limited knowledge of how to use the aggregation framework seems to be catching me out.
My intended result, if there were one distinct manufacturers with two distinct ranges, would be the following:
[
{
"manufacturer": "Manufacturer A",
"range": "Range A",
"minimumRental": 123.45,
"minimumPayment": 98.76
},
{
"manufacturer": "Manufacturer A",
"range": "Range B",
"minimumRental": 234.56,
"minimumPayment": 197.53
}
]
I'm using the following to try and achieve this, but I seem to be tripping up on the grouping and use of $min
:
db.products.aggregate(
[
{
"$group": {
"_id": {
"manufacturer": "$manufacturer.name",
"range": "$range.name"
},
"rentals": {
"$addToSet": "$rentals.monthlyrental"
},
"payments": {
"$addToSet": "$payments.monthlypayment"
}
}
},
{
"$group": {
"_id": {
"manufacturer": "$_id.manufacturer",
"range": "$_id.range",
"payments": "$payments"
},
"minimumRental": {
"$min": "$rentals"
}
}
},
{
"$project": {
"_id": {
"manufacturer": "$_id.manufacturer",
"range": "$_id.range",
"minimumRental": "$minimumRental",
"payments": "$_id.payments"
}
}
},
{
"$group": {
"_id": {
"manufacturer": "$_id.manufacturer",
"range": "$_id.range",
"minimumRental": "$_id.minimumRental"
},
"minimumPayment": {
"$min": "$_id.payments"
}
}
},
{
"$project": {
"_id": 0,
"manufacturer": "$_id.manufacturer",
"range": "$_id.range",
"minimumRental": "$_id.minimumRental",
"minimumPayment": "$minimumPayment"
}
}
]
)
It's worth noting, in the case with my test data, that I have deliberately not specified a rental for Range B, as there will be cases where rentals and/or payments are not both specified for a given range.
So, using the query above on my test data gives me the following:
{
"0" : {
"minimumPayment" : [
98.76
],
"manufacturer" : "Manufacturer A",
"range" : "Range A",
"minimumRental" : [
123.45
]
},
"1" : {
"minimumPayment" : [
197.53
],
"manufacturer" : "Manufacturer A",
"range" : "Range B",
"minimumRental" : []
}
}
This is close, but it appears that I'm getting an array instead of a minimum value. I get the impression that what I'm trying to do is possible, but I don't seem to be able to find any resources specific enough to use to find out what I'm doing wrong.
Thanks for reading.