首页 > 解决方案 > 仅在 mongodb 聚合中匹配时间

问题描述

我每天将开放时间存储为一系列班次,如下所示:

{
  Monday: [{
    startTime: {
      hour: 8, 
      minute: 50
    },
    endTime: {
      hour: 20, 
      minute: 30
    }
  }];
}

在此处输入图像描述

我正在尝试使用$match如下所示的 MongoDB 聚合运算符检索班次开始和结束之间的文档:

{
  $match: {
    'Monday.startTime.hour': {              // ex: 8
      $lte: parseInt(now.format('HH'), 10), // now hours: 18
    },
    'Monday.startTime.minute': {            // ex: 50
      $lte: parseInt(now.format('mm'), 10), // now minutes: 40
    },
    'Monday.endTime.hour': {                // ex: 20
      $gte: parseInt(now.format('HH'), 10), // now hours: 18
    },
    'Monday.endTime.minute': {              // ex: 30
      $gte: parseInt(now.format('mm'), 10), // now minutes: 40
    },
  }
}

问题是我们有一个如下图所示的移位示例, 第一个匹配条件:

'Monday.startTime.hour': {
  $lte: parseInt(now.format('HH'), 10),
}

将通过,因为 8 小于 18。

但与分钟部分匹配的第二个匹配条件:

'Monday.startTime.minute': {            // ex: 50
  $lte: parseInt(now.format('mm'), 10), // now minutes: 40
},

将失败,因为 50 大于 40

虽然在现实生活08:5018:40

标签: javascriptnode.jsmongodbdatetimemongoose

解决方案


我能够通过首先使用比较小时数来解决这个问题,$and运算$or符参见下面的解释代码:

{
  $and: [ // grouping two conditions that now time needs to be between the start and the end of the shift.
    {
      $or: [ // compare the start time hour of the shift first 
        {
          'Monday.startTime.hour': {
            $lt: parseInt(now.format('HH'), 10),
          },
        },
        {
          $and: [ // if the upper condition didn't work will need to compare hours and minutes 
            {
              'Monday.startTime.hour': {
                $lte: parseInt(now.format('HH'), 10),
              },
            },
            {
              'Monday.startTime.minute': {
                $lte: parseInt(now.format('mm'), 10),
              },
            },
          ],
        },
      ],
    },
    {
      $or: [ // compare the end time hour of the shift first 
        {
          'Monday.endTime.hour': {
            $gt: parseInt(now.format('HH'), 10),
          },
        },
        {
          $and: [ // if the upper condition didn't work will need to compare hours and minutes
            {
              'Monday.endTime.hour': {
                $gte: parseInt(now.format('HH'), 10),
              },
            },
            {
              'Monday.endTime.minute': {
                $gte: parseInt(now.format('mm'), 10),
              },
            },
          ],
        },
      ],
    },
  ];
}

推荐阅读