I need help with a bit more complex version of sorting than usual. So I have times: [Date]
field in scheme. Let's say my DB has 2 items with these fields:
- a)
time: [ "2022-12-28T18:00:00.000 00:00", "2023-01-04T18:00:00.000 00:00" ]
. - b)
time: [ "2022-12-30T18:00:00.000 00:00" ]
.
My query:
const today = new Date().toISOString().split("T")[0];
...
.find({ times: { $gte: today } }).sort("times")
Because today is 2022-12-29, .sort("times")
or .sort({ times: 1 })
will sort events in a way, that item "a)" will be sorted first, because from "now" Dec 28 is closer than 30, so it works correctly.
What I want is to ignore dates that are 1 days old. It should consider dates that are today and all in the future, but not yesterday or later in the past.
I thought about querying all items once per day to and removing all past dates, but I kind of want to keep them. Is there a solution with aggregation for this problem?
EDIT: added algorithm for sorting array of dates
export const sortDateByClosest = datesArray => {
if (datesArray.length === 1) return datesArray;
const today = new Date();
const yesterday = new Date(new Date().setDate(new Date().getDate() - 1));
const sorted = datesArray.sort((a, b) => {
const distanceA = Math.abs(today - a);
const distanceB = Math.abs(today - b);
return distanceA - distanceB;
});
// remove times that were before yesterday
return sorted.filter(d => d - yesterday > 0);
};
CodePudding user response:
I think it works You want to ignore 1 days older dates then you need to use aggregation like this:
db.collectionName.aggregate([
{
"$match": {
'times': {
'$gte': today,
}
}
}, { $unwind: '$times' }, {
$sort : {
times: 1
}
}
])
CodePudding user response:
Aggregation be like:
{ $unwind: "$times" },
{
$match: {
times: { "$gte": today }
},
},
{
$sort: {
times: 1,
},
},
{
$group: {
_id: "$_id",
times: { $push: "$times" },
otherStuff: { $first: "$otherStuff" },
...
}
},
But it doesn't show very good results in terms of scalability