在MongoDB中计算日期范围(不包括周末和节假日)

时间:2019-04-06 03:46:03

标签: mongodb aggregation-framework

我的目标是确认符合MongoDB Atlas 4.0.6中存储的必需活动日历。此计算必须在MongoDB Aggregation Framework内进行。

类似的帖子介绍了使用RubyJSSQL的方法,但是我发现没有一种方法可以直接解决聚合框架。

MongoDB集合 requiredActivities 指定了事件的预期发生频率(例如,每“ 4周”进行“老教师观察”)。频率可能以天或周为单位。

    {
    "_id" : ObjectId("5c9ee1e03735761f24721b0b"),
    "title" : "Veteran Teacher Observation",
    "durationUnit" : "weeks",
    "durationCount" : 4
    },
    {
    "_id" : ObjectId("5c9ee1e03735761f24721b0b"),
    "title" : "New Teacher Observation",
    "durationUnit" : "days",
    "durationCount" : 5
    }

另一个收藏集假期标识假日。

[
{
    "_id" : ObjectId("5ca807eaf1764b1f507350f0"),
    "date" : ISODate("2018-12-20T00:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
},
{
    "_id" : ObjectId("5ca8089df1764b1f507350f2"),
    "date" : ISODate("2018-12-21T16:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
},
{
    "_id" : ObjectId("5ca808acf1764b1f507350f4"),
    "date" : ISODate("2018-12-24T16:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
},
{
    "_id" : ObjectId("5ca808f0f1764b1f507350f7"),
    "date" : ISODate("2018-12-25T16:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
},
{
    "_id" : ObjectId("5ca8090bf1764b1f507350f8"),
    "date" : ISODate("2018-12-31T16:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
},
{
    "_id" : ObjectId("5ca8091af1764b1f507350f9"),
    "date" : ISODate("2019-01-01T16:00:00.000-08:00"),
    "description" : "Winter Break",
    "isHoliday" : true
}
]

鉴于endDate,所需结果是一个文件,该文件标识了针对周末和节假日更正的合规期限。结果中必须显示排除的周末和节假日。

给定endDate为01/02/2019的所需结果是:

{
    "_id" : ObjectId("5c9ee1e03735761f24721b0b"),
    "title" : "Veteran Teacher Observation",
    "durationUnit" : "weeks",
    "durationCount" : 4,
    "dateRangeIncludingWeekendsAndHolidays" : {
        "start" : ISODate("2018-12-05T00:00:00.000-08:00"),
        "end" : ISODate("2019-01-02T00:00:00.000-08:00")
    },
    "holidays" : [
        ISODate("2018-12-20T00:00:00.000-08:00"),
        ISODate("2018-12-21T00:00:00.000-08:00"),
        ISODate("2018-12-24T00:00:00.000-08:00"),
        ISODate("2018-12-25T00:00:00.000-08:00"),
        ISODate("2018-12-31T00:00:00.000-08:00"),
        ISODate("2018-01-01T00:00:00.000-08:00")
    ],
    "weekendDays" : [
        ISODate("2018-12-01T00:00:00.000-08:00"),
        ISODate("2018-12-02T00:00:00.000-08:00"),
        ISODate("2018-12-08T00:00:00.000-08:00"),
        ISODate("2018-12-09T00:00:00.000-08:00"),
        ISODate("2018-12-15T00:00:00.000-08:00"),
        ISODate("2018-12-16T00:00:00.000-08:00"),
        ISODate("2018-12-22T00:00:00.000-08:00"),
        ISODate("2018-12-23T00:00:00.000-08:00"),
        ISODate("2018-12-29T00:00:00.000-08:00"),
        ISODate("2018-12-30T00:00:00.000-08:00")
    ],
    "dateRangeExcludingWeekendsAndHolidays" : {
        "start" : ISODate("2018-11-21T00:00:00.000-08:00"),
        "end" : ISODate("2019-01-02T00:00:00.000-08:00")
    }
}

以下查询是部分解决方案。它无需周末或假日即可处理计算。 可以修改此查询以说明周末和节假日吗?是否有更好的方法?

const endDate = new ISODate("2019-01-02T00:00:00.000-08:00");
endDate.setHours(0, 0, 0, 0);

const ms1d = 24 * 60 * 60 * 1000; /* milliseconds per day */
const ms1w = 7 * ms1d; /* milliseconds per week */

db.requiredActivities.aggregate([
  {
    $addFields: {
      dateRange: {
        $cond: {
          if: { $eq: ["$durationUnit", "weeks"] },
          then: {
            start: {
              $subtract: [endDate, { $multiply: [ms1w, "$durationCount"] }]
            },
            end: endDate
          },
          else: {
            start: {
              $subtract: [endDate, { $multiply: [ms1d, "$durationCount"] }]
            },
            end: endDate
          }
        }
      }
    }
  }
]);

0 个答案:

没有答案