skip to Main Content

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);
};

2

Answers


  1. Chosen as BEST ANSWER

    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


  2. I think it works You want to ignore 1+ days older dates then you need to use aggregation like this:

    db.collectionName.aggregate([ { $unwind: '$times' },
      {
        "$match": {
          'times': {
            '$gte': today, 
           }
         }
      }, {
        $sort : {
          times: 1
        }
      }
    ])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search