Search code examples
mongodbdateaggregation-frameworkcomputed-field

Meteor MongoDB: How to aggregate date-range with computed end-date from collection field?


I'm using meteorhacks:aggregate package for Meteor, and I'm trying to find Events within a date-range between:

  • now, minus one day.
  • the end-date of the Event, plus two weeks.

Problem is, the end-date is stored in the Event document, in a field at times.until. The Event document looks like this:

// Event collection doc:
{
  _id: 'abc',
  times: {
    start: {
      dateTime: "ISODate("2017-03-07T00:00:00Z"),
      timeZone : "America/Chicago"
    },
    until: "20170307T000000Z"
  }
}

I able to aggregate to find dates in a range, but I can't figure out how to compute an end-date for the range based on the Event's times.until field.

if (Meteor.isServer) {
  Meteor.methods({
    'events.inProgress'() {
      const start = moment().utc().subtract(1, 'day').toDate();

      return Events.aggregate([
        {$match: {"times.start.dateTime": {$gt: start, $lt: end**(MUST COMPUTE end FROM DOC'S times.until PLUS 2 WEEKS)**}}},
      ]);
    }
  }
}

Also, note the format of the times.until field is 20170307T000000Z (not sure the correct name of this format). This is not a valid format for a JavaScript Date, but moment.js handles this String no problem. With access to the times.until field, I can do:

const end = moment(event.times.until).add(2, 'week').toDate();

This does give me the correct end-date of the range, but how can I grab the times.until field to compute the end-date while constructing the pipeline?


Solution

  • Use $add to add the milliseconds to get the date you want. Ofcourse this means the times.until is mongo date type.

    aggregate([{
        $match: {
            "times.start.dateTime": {
                $gt: start,
                $lt: {
                    $add: ["$times.until", 14 * 24 * 60 * 60000]
                }
            }
        }
    }])