Reputation: 129
Assume I have the following document:
[
{
"callId": "17dac51e-125e-499e-9064-f20bd3b1a9d8",
"caller": {
"firstName": "Test",
"lastName": "Testing",
"phoneNumber": "1231231234"
},
"routeHistory": [
{
"assignedUserId": "cfa0ffe9-c77d-4eec-87d7-4430f7772e81",
"routeDate": "2020-01-01T06:00:00.000Z",
"status": "routed"
},
{
"assignedUserId": "cfa0ffe9-c77d-4eec-87d7-4430f7772e81",
"routeDate": "2020-01-03T06:00:00.000Z",
"status": "ended"
}
]
}
]
I want to get results where routeHistory.routeDate is equal to the $max routeDate value in routeHistory. I would expect my results to look like the following:
[
{
"callId": "17dac51e-125e-499e-9064-f20bd3b1a9d8",
"caller": {
"firstName": "Test",
"lastName": "Testing",
"phoneNumber": "1231231234"
},
"routeHistory": [
{
"assignedUserId": "cfa0ffe9-c77d-4eec-87d7-4430f7772e81",
"routeDate": "2020-01-03T06:00:00.000Z",
"status": "ended"
}
]
}
]
Is there a clean way to do this in a single aggregate, so that additional $match criteria can be applied?
Upvotes: 1
Views: 2263
Reputation: 49985
You can use $let to define temporary variable being $max
date and the use $filter along with $arrayElemAt to get first matching element:
db.collection.aggregate([
{
$addFields: {
routeHistory: {
$let: {
vars: {
maxDate: { $max: "$routeHistory.routeDate" }
},
in: {
$arrayElemAt: [
{ $filter: { input: "$routeHistory", cond: { $eq: [ "$$maxDate", "$$this.routeDate" ] } } },
0
]
}
}
}
}
}
])
EDIT:
version without $let
:
db.collection.aggregate([
{
$addFields: {
maxDate: {
$max: "$routeHistory.routeDate"
}
}
},
{
$addFields: {
routeHistory: {
$arrayElemAt: [
{
$filter: { input: "$routeHistory", cond: { $eq: [ "$$maxDate", "$$this.routeDate" ] } }
},
0
]
}
}
}
}
])
Upvotes: 2