MongoDB 与 $or 和 $and 的聚合
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')
}
}
]
以上管道将 return 在给定时间跨度内开始和结束的每个班次。但我也想得到开始和结束日期与时间跨度重叠的所有班次。
因此,例如,我希望它也能找到从 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 的是您不需要的离群值。
Mongo Playground
我有以下 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')
}
}
]
以上管道将 return 在给定时间跨度内开始和结束的每个班次。但我也想得到开始和结束日期与时间跨度重叠的所有班次。
因此,例如,我希望它也能找到从 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 的是您不需要的离群值。
Mongo Playground