Created
August 3, 2017 08:54
-
-
Save Agoreddah/cb65b72e6c7a35691b4a5dc179ec2759 to your computer and use it in GitHub Desktop.
Calculate price with mongo aggregate query - Evaluate array of dates with array of prices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple document example | |
// Every boat contains array of prices for different days | |
// We decided to use simple concatenated date int to evaluate date ranges, f.e. date '2017-08-24' becomes integer 20170824 | |
// If user wants to reservate boat in dates when prices is not defined, it will not be shown in results | |
Boat = { | |
_id : ObjectId("100000000000000000000001"), | |
prices : [ | |
// price available for august | |
{ | |
price : NumberInt(100), | |
check_in : NumberInt(20170801), | |
check_out : NumberInt(20170831) | |
}, | |
// price available for september | |
{ | |
price : NumberInt(50), | |
check_in : NumberInt(20170901), | |
check_out : NumberInt(20170930) | |
} | |
] | |
} | |
// period: | |
// -- we used to generate price for every day differently | |
// -- dates array is generated automatically from user's checkIn and checkOut dates | |
// -- dates array contains minimum 1 day, and maximum 28 days | |
// -- last date of reservation is not calculated - user returns boat and it's available for another user | |
// example: user wants to rent a yacht for 1 week in august, from 12. to 19. | |
var period = [20170812,20170813,20170814,20170815,20170816,20170817,20170818]; | |
db.boats.aggregate([ | |
{ | |
$project : { | |
data : { | |
_id : '$_id', | |
dates : period, | |
prices : { | |
$map : { | |
input : period, | |
as : 'date', | |
in : { | |
// $filter returns array, we need to get data from it's index 0 | |
$arrayElemAt : [{ | |
$filter : { | |
input : '$prices', | |
as : 'price', | |
cond : { | |
$and : [ | |
{ $gte : ['$$date', '$$price.check_in']}, | |
{ $lte : ['$$date', '$$price.check_out']} | |
] | |
} | |
} | |
}, 0] | |
} | |
} | |
} | |
} | |
} | |
}, | |
{ | |
$match : { | |
// if boat doesn't have prices set for user's checkIn & checkOut dates, $filter returns null | |
'data.prices' : { $ne : null } | |
} | |
}, | |
{ | |
// group the results | |
$group : { | |
_id : '$data._id', | |
prices : { $first : '$data.prices' } | |
} | |
}, | |
{ | |
// $prices contains array of objects, we would like to return only price integers | |
$unwind : '$prices' | |
}, | |
{ | |
// now $prices is an array of integers (prices) per day | |
// totalPrice is sum of all $prices | |
$group : { | |
_id : '$_id', | |
prices : { $push : '$prices.price' }, | |
totalPrice : { $sum : '$prices.price' } | |
} | |
} | |
]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment