node.js - 查询事件数组以查找我添加的事件是否重叠(Express/Mongoose)

标签 node.js mongodb express mongoose

我有一个带有文档集合的 mongo 数据库,其中每个元素都有一个收集事件的繁忙数组。 Mongoose 模型如下:

busy: [{
      _id : Schema.Types.ObjectId,
      isBusy : Boolean,
      eventType : String,
      title : String,
      startDate : Date,
      endDate : Date,
      event: {type: Schema.Types.ObjectId, ref: 'Event', index: true },
    }],

当它被填充时,我想查询数组中没有与我尝试添加的事件同时发生的事件的所有文档,因此我只能选择不忙的文档那一刻。

我正在使用的查询是

{
  "user.busy": {
    $not: {
      $elemMatch: {
        'startDate': {
          $gte: startDate,
          $lt: endDate
        },
        'endDate': {
          $gte: startDate,
          $lt: endDate
        },
        isBusy: true
      }
    }
  }
}

而且它不起作用。 关于我应该如何继续执行此操作有任何提示吗?

---示例数据

这是我的数据库中繁忙数组的示例

"busy" : [ 
            {
                "isBusy" : true,
                "eventType" : "Shooting",
                "title" : "Shooting",
                "startDate" : ISODate("2018-08-23T00:00:28.000Z"),
                "endDate" : ISODate("2018-08-23T03:00:28.000Z"),
                "event" : ObjectId("5b5573fcba399fababcb200d")
            }, 
            {
                "isBusy" : true,
                "eventType" : "Shooting",
                "title" : "Shooting",
                "startDate" : ISODate("2018-08-23T06:30:28.000Z"),
                "endDate" : ISODate("2018-08-23T09:30:28.000Z"),
                "event" : ObjectId("5b557410ba399fababcb2013")
            }, 
            {
                "isBusy" : true,
                "eventType" : "Shooting",
                "title" : "Shooting",
                "startDate" : ISODate("2018-08-23T10:11:06.000Z"),
                "endDate" : ISODate("2018-08-23T13:11:06.000Z"),
                "event" : ObjectId("5b5580216a5615aca0d089e0")
            }, 
            ],

--编辑1

由于查询在数据库上原始完成时有效,因此可能是我的 Mongoose 实现中的某些内容,按如下方式完成

Element.find({ 
 "user.busy" : 
   { $not : 
     { $elemMatch : 
       {
         'startDate' : { $gte: startDate, $lt: endDate }, 
         'endDate' : { $gte: startDate, $lt: endDate }, 
         isBusy : true 
       } 
     } 
   } 
 })
.exec()
.then(...)

最佳答案

输入:

{
    "_id" : ObjectId("5b6495b4611de4551f5eb8d4"),
    "user" : {
        "busy" : [ 
            {
                "_id" : ObjectId("5b6493b5611de4551f5eb878"),
                "isBusy" : true,
                "eventType" : "Shooting",
                "title" : "Shooting",
                "startDate" : ISODate("2018-01-23T00:00:28.000Z"),
                "endDate" : ISODate("2018-08-23T03:00:28.000Z"),
                "event" : ObjectId("5b5573fcba399fababcb200d")
            }, 
            {
                "_id" : ObjectId("5b649486611de4551f5eb89f"),
                "isBusy" : true,
                "eventType" : "Shooting",
                "title" : "Shooting",
                "startDate" : ISODate("2018-08-23T10:11:06.000Z"),
                "endDate" : ISODate("2018-10-23T13:11:06.000Z"),
                "event" : ObjectId("5b5580216a5615aca0d089e0")
            }
        ]
    }
}    
{
    "_id" : ObjectId("5b6495e5611de4551f5eb8df"),
    "user" : {
        "busy" : [ 
            {
                "_id" : ObjectId("5b6493b5611de4551f5eb878"),
                "isBusy" : true,
                "eventType" : "Playing Games",
                "title" : "MORTAL KOMBAT",
                "startDate" : ISODate("2017-04-23T00:00:28.000Z"),
                "endDate" : ISODate("2017-06-23T03:00:28.000Z"),
                "event" : ObjectId("5b5573fcba399fababcb200d")
            }, 
            {
                "_id" : ObjectId("5b6493bf611de4551f5eb87a"),
                "isBusy" : true,
                "eventType" : "Coding",
                "title" : "JavaScript",
                "startDate" : ISODate("2017-07-23T06:30:28.000Z"),
                "endDate" : ISODate("2017-08-23T09:30:28.000Z"),
                "event" : ObjectId("5b557410ba399fababcb2013")
            }
        ]
    }
}

使用 $not 的一般经验法则是创建一个您知道它有效的查询,并使用 $not 来否定它。 所以你必须找到我x,然后一切不等于(也不存在)的x。因此,让我们创建 find me x:

var startDate = ISODate("2017-11-23T00:00:28.000Z"),
    endDate = ISODate("2018-09-23T03:00:28.000Z")

db.getCollection('busy').find({
  "user.busy": {
      $elemMatch: {          
        'startDate': {
            $gte: startDate,
            $lt: endDate
        },          
        'endDate': {
            $gte: startDate,
            $lt: endDate
        },
        isBusy: true
      }
    }
})

这将返回带有 _id : ObjectId("5b6495b4611de4551f5eb8d4") 的用户,如果您仔细查看代码中提供的日期和 2 个日期范围,这是正确的结果。该用户在 2017 年 11 月 23 日和 2018 年 9 月 23 日期间很忙,因为他在 2018 年 1 月 23 日至 2018 年 08 月 23 日期间有拍摄事件 ("_id": ObjectId("5b6493b5611de4551f5eb878"))。到目前为止,一切都很好。现在让我们添加 $not:

db.getCollection('busy').find({
  "user.busy": {
    $not: {
      $elemMatch: {          
        'startDate': {
            $gte: startDate,
            $lt: endDate
        },          
        'endDate': {
            $gte: startDate,
            $lt: endDate
        },
        isBusy: true
      }
    }
  }
})

结果是用户“_id”:ObjectId(“5b6495e5611de4551f5eb8df”)。这又是正确的结果,因为该用户在 2017 年 11 月 23 日和 2018 年 9 月 23 日的日期范围内没有任何事件。

结论...您的查询有效! :)

关于node.js - 查询事件数组以查找我添加的事件是否重叠(Express/Mongoose),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51676638/

相关文章:

node.js - 使用 NODE for Windows SQL 2012 进行 ActiveDirectory 身份验证

javascript - MongoDB:当前字段总和

ios - iPhone/Android 不会关闭使用 DNS 实现的 wifi 登录页面

node.js - nodejs npm 包安装失败

node.js - 对 Node/Express 应用程序使用 connect-flash 时无法获取要渲染的 Flash 消息

node.js - 将 node-restful 与 mongoose.createConnection 结合使用

javascript - Dockerfile,在dev/prod之间切换

node.js - 上传媒体文件后无法在 Angular 2中播放该文件,显示404未找到

php - mongo.so : > undefined symbol: php_json_encode in Unknown on line 0. 为php安装mongo驱动后

node.js - mongodb 集合中的更改