So the idea is
- Sort the
customerSchemes array by startDate.
- Pick the first item from the sorted list.
- Include it only if the
customerSchemes.name is A.
Try this query:
db.collection.aggregate([
{ $unwind: "$customerSchemes" },
{
$sort: { "customerSchemes.startDate": 1 }
},
{
$group: {
_id: "$_id",
customerSchemes: { $push: "$customerSchemes" }
}
},
{
$match: {
$expr: {
$eq: [{ $first: "$customerSchemes.name" }, "A"]
}
}
}
]);
Output:
/* 1 createdAt:3/12/2021, 6:40:42 PM*/
{
"_id" : ObjectId("604b685232a8d433d8ede6c4"),
"customerSchemes" : [
{
"name" : "A",
"startDate" : ISODate("2021-03-01T00:00:00.000+05:30")
},
{
"name" : "B",
"startDate" : ISODate("2021-03-02T00:00:00.000+05:30")
}
]
},
/* 2 createdAt:3/12/2021, 6:40:42 PM*/
{
"_id" : ObjectId("604b685232a8d433d8ede6c6"),
"customerSchemes" : [
{
"name" : "A",
"startDate" : ISODate("2021-03-01T00:00:00.000+05:30")
},
{
"name" : "B",
"startDate" : ISODate("2021-03-05T00:00:00.000+05:30")
}
]
}
Test data:
/* 1 createdAt:3/12/2021, 6:40:42 PM*/
{
"_id" : ObjectId("604b685232a8d433d8ede6c4"),
"customerSchemes" : [
{
"name" : "A",
"startDate" : ISODate("2021-03-01T00:00:00.000+05:30")
},
{
"name" : "B",
"startDate" : ISODate("2021-03-02T00:00:00.000+05:30")
}
]
},
/* 2 createdAt:3/12/2021, 6:40:42 PM*/
{
"_id" : ObjectId("604b685232a8d433d8ede6c5"),
"customerSchemes" : [
{
"name" : "A",
"startDate" : ISODate("2021-03-03T00:00:00.000+05:30")
},
{
"name" : "B",
"startDate" : ISODate("2021-03-02T00:00:00.000+05:30")
}
]
},
/* 3 createdAt:3/12/2021, 6:40:42 PM*/
{
"_id" : ObjectId("604b685232a8d433d8ede6c6"),
"customerSchemes" : [
{
"name" : "B",
"startDate" : ISODate("2021-03-05T00:00:00.000+05:30")
},
{
"name" : "A",
"startDate" : ISODate("2021-03-01T00:00:00.000+05:30")
}
]
}
Dateobject. There is really no reason for storing dates as string$reduceoperator to return a boolean based upon the comparison.customerSchemesarray? What are Plan A and Plan B - are they same as the scheme A and B? Are there any other schemes other than A and B?