Assume I have the following document:
[
{
"callId": "17dac51e-125e-499e-9064-f20bd3b1a9d8",
"caller": {
"firstName": "Test",
"lastName": "Testing",
"phoneNumber": "1231231234"
},
"inquiries": [
{
"inquiryId": "b0d14381-ce75-49aa-a66a-c36ae20b72a8",
"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"
}
]
},
{
"inquiryId": "9d743be9-7613-46d7-8f9b-a04b4b899b56",
"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 inquiries.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"
},
"inquiries": [
{
"inquiryId": "b0d14381-ce75-49aa-a66a-c36ae20b72a8",
"routeHistory": [
{
"assignedUserId": "cfa0ffe9-c77d-4eec-87d7-4430f7772e81",
"routeDate": "2020-01-03T06:00:00.000Z",
"status": "ended"
}
]
},
{
"inquiryId": "9d743be9-7613-46d7-8f9b-a04b4b899b56",
"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? One caveat is that I can only use operators supported by DocumentDB: https://docs.aws.amazon.com/documentdb/latest/developerguide/mongo-apis.html
I have tried the following code, but to no avail:
{
$addFields: {
maxDate: {
$max: '$inquiries.routeHistory.routeDate',
},
},
},
{
$addFields: {
routeHistory: [
{
$arrayElemAt: [
{
$filter: {
input: '$inquiries.routeHistory',
cond: {
$eq: ['$maxDate', '$$this.routeDate'
],
},
},
},
0,
],
},
],
},
}
You have to use $map to scan outer array and to $filter to compare inner array’s elements against $max date:
db.collection.aggregate([
{
$addFields: {
inquiries: {
$map: {
input: "$inquiries",
as: "inquiry",
in: {
inquiryId: "$$inquiry.inquiryId",
routeHistory: {
$filter: {
input: "$$inquiry.routeHistory",
cond: {
$eq: [ { $max: "$$inquiry.routeHistory.routeDate" }, "$$this.routeDate" ]
}
}
}
}
}
}
}
}
])
EDIT: by looking at your link I’ve noticed that $map
is not supported, you can use below combination as a workaround:
db.collection.aggregate([
{
$unwind: "$inquiries"
},
{
$addFields: {
"inquiries.routeHistory": {
$filter: {
input: "$inquiries.routeHistory",
cond: {
$eq: [ { $max: "$inquiries.routeHistory.routeDate" }, "$$this.routeDate" ]
}
}
}
}
},
{
$group: {
_id: "$_id",
callId: { $first: "$callId" },
caller: { $first: "$caller" },
inquiries: { $push: "$inquiries" }
}
}
])