繁体   English   中英

使用 $or 和 $and 进行 MongoDB 聚合

[英]MongoDB Aggregation with $or and $and

我有以下 MonogoDb 集合

ShiftMgmt.shiftSchema = new mongoose.Schema({
    assignedUser: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'users' },
    shiftType: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'shiftTypes' },
    team: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'teams' },
    startDate: { type: Number, required: true },
    endDate: { type: Number, required: true }
});

我想获得与给定时间跨度重叠的给定 ShiftType 的所有班次。

假设从 2021-07-19 (1626652800000) 到 2021-07-23 (1626998400000)

[
  {
    '$match': {
      'startDate': {
        '$gte': 1626652800000
      }, 
      'endDate': {
        '$lte': 1626998400000
      }, 
      'shiftType': new ObjectId('60a36ea2e2f5035b26f23430')
    }
  }
]

以上管道将返回在给定时间跨度内开始和结束的每个班次。 但我也想获得开始和结束日期与时间跨度重叠的所有班次。

因此,例如,我希望它还可以找到从 2021-07-16 开始但将在 2021-07-21 结束的班次以及将在 2021-07-20 开始并于 2021-07-25 结束的班次.

我想要实现这一点,我需要 $and 和 $or 在我的管道中,但是我在找到正确的语法时遇到了问题。 到目前为止,这是我的非工作管道:

let date1 = 1626652800000 // 2021-07-19
let date2 = 1627041600000 // 2021-07-23

[
  {
    '$match': {
        '$or': [ 
            '$and': [ // shift lies betweend dates
                'startDate': {
                    '$gte': date1
                },
                'endDate': {
                    '$lte': date2
                }
            ],
            '$and': [ // shift starts before timespan and ends in time span
                "startDate": {
                    '$lte': date1
                },
                "endDate" {
                    '$gte': date1
                }
            ],
            '$and': [ // shift starts in timespan and ends after time span
                "startDate": {
                    '$lte': date2
                },
                "endDate" {
                    '$gte': date2
                }
            ],
            '$and': [ // shift starts before timespand and ends after time span
                "startDate": {
                    '$lte': date1
                },
                "endDate" {
                    '$gte': date2
                }
            ]
        ],
        'shiftType': ObjectId('60a36ea2e2f5035b26f23430')
    }
  }
]

解决方案感谢 Koodies 我能够像这样解决它:

[
  {
    '$match': {
      '$or': [
        {
          'startDate': {
            '$gte': 1625443200000, 
            '$lte': 1625788800000
          }
        }, {
          'endDate': {
            '$lte': 1625788800000, 
            '$gte': 1625443200000
          }
        }, {
          '$and': [
            {
              'startDate': {
                '$lte': 1625443200000
              }
            }, {
              'endDate': {
                '$gte': 1625788800000
              }
            }
          ]
        }
      ], 
      'shiftType': new ObjectId('60a278355c7462f42b3d7895')
    }
  }
]

您正朝着正确的方向前进,但您无需使用 $and。 这是您的逻辑可以派生的方式,只需替换 startTime 和 endTime。

db.collection.aggregate([
  {
    $match: {
      "$or": [
        {
          "startDate": {
            "$gte": startTime,
            "$lte": endTime
          }
        },
        {
          "endDate": {
            "$lte": endTime,
            "$gte": startTime
          }
        }
      ]
    }
  }
])

我在 mongo playground 上创建了一个包含 5 个文档的快速示例。 带有计数器 4 和 5 的那个是您不需要的异常值。
蒙戈游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM