I'm trying to filtering some date data by starting using $unwind
for destructing the date array:
"startDates": [
"2024-05-15T09:30:00.000Z",
"2024-11-13T10:00:00.000Z",
"2024-02-10T00:00:00.000Z"
]
using:
{
$unwind: "$startDates",
},
and then use $match
for filtering date data with years:
{
$match: {
startDates: {
$gte: new Date(`${year}-01-01`),
$lte: new Date(`${year}-12-31`),
},
},
},
but the response is return an empty array
{
"status": "Success",
"result": 0,
"data": {
"plan": []
}
}
but when i remove new Date
and write the date manually the response return the data i want
like that:
{
$match: {
startDates: {
$gte: `${year}-01-01`,
$lte: `${year}-12-31`,
},
},
},
but then when i try to group the data with $group
and using $month
pupline it show me this error:
{
"status": "failed",
"message": "PlanExecutor error during aggregation :: caused by :: can't convert from BSON type string to Date"
}
this is the full function code:
exports.getMonthlyPlan = async (req, res) => {
try {
const year = req.params.year * 1;
const plan = await Tour.aggregate([{
$unwind: "$startDates",
},
{
$match: {
startDates: {
$gte: `${year}-01-01`,
$lte: `${year}-12-31`,
},
},
},
{
$group: {
_id: {
$month: "$startDates"
},
numTourStarts: {
$sum: 1
},
},
},
]);
res.status(200).json({
status: "Success",
result: plan.length,
data: {
plan,
},
});
} catch (error) {
res.status(400).json({
status: "failed",
message: error.message,
});
}
};
I hope I have explained the problems in a clear way
i'm trying to play with new Date
function but i don"t understand the issue
Storing date values a string is a design flaw, you should never do that. Store always proper Date
objects.
First you can convert the data type with an update like this:
db.collection.updateMany(
{ startDates: { $type: "string" } },
[
{
$set: {
startDates: {
$map: {
input: "$startDates",
in: { $dateFromString: { dateString: "$$this" } }
}
}
}
}
]
)
Then your query will work. This one may give better performance:
db.gcollection.aggregate([
{
$match: {
startDates: {
$gte: new Date(`${year}-01-01`),
$lte: new Date(`${year}-12-31`)
}
}
},
{
$set: {
startDates: {
$filter: {
input: "$startDates",
cond: { $eq: [{ $year: "$$this" }, year] }
}
}
}
},
{ $unwind: "$startDates" },
{
$group: {
_id: { $month: "$startDates" },
numTourStarts: { $count: {} }
}
}
])