【问题标题】:MongoDB/Mongoose querying at a specific date?MongoDB/Mongoose 在特定日期查询?
【发布时间】:2012-08-11 23:37:38
【问题描述】:

是否可以查询具体日期?

我在 mongo Cookbook 中发现我们可以在一个范围内做到这一点 Querying for a Date Range 像这样:

db.posts.find({"created_on": {"$gte": start, "$lt": end}})

但是是否有可能在特定日期? 这不起作用:

db.posts.find({"created_on": new Date(2012, 7, 14) })

【问题讨论】:

    标签: node.js mongodb express mongoose odm


    【解决方案1】:

    如果您保存在数据库中的日期没有时间(只是年、月、日),这应该可以工作。

    您保存的日期可能是new Date(),其中包括时间部分。要查询这些时间,您需要创建一个包含一天中所有时刻的日期范围。

    db.posts.find({ //query today up to tonight
        created_on: {
            $gte: new Date(2012, 7, 14), 
            $lt: new Date(2012, 7, 15)
        }
    })
    

    【讨论】:

    • 请记住,在 Date() 函数中,月份参数从 0 开始计数,而不是 1。另一方面,天从 1 开始计数...details
    • 用_1天来获得下一个日期而不是硬编码它们不是更好吗?
    • 如果日期是这样存储的,这个方法是否可以正常工作:>>"date" : ISODate("2016-01-04T14:07:17.496Z")
    • 您没有月份和日期开关。日期格式应为:yyyy, dd, MM
    • @thethakuri stackoverflow.com/users/2529191/thethakuri 他们什么时候有过 yyyy, dd, MM 顺序?显示记录在哪里。
    【解决方案2】:

    你试过了吗:

    db.posts.find({"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})
    

    您将遇到的问题是日期在 Mongo 中存储为时间戳。因此,要匹配日期,您要求它匹配时间戳。在您的情况下,我认为您正在尝试匹配一天(即从特定日期的 00:00 到 23:59)。如果您的日期没有时间存储,那么您应该没问题。否则,如果 gte 不起作用,请尝试将您的日期指定为同一天的时间范围(即 start=00:00,end=23:59)。

    similar question

    【讨论】:

    • 这将包括所有比指定日期更年轻的元素,这可能不是 OP 想要的。考虑像其他答案一样添加“lt”选项。
    • 我认为如果你有$gte 而不是gte 会更好。
    • 这已经在上面得到了更正确的回答,但是我知道我的答案是关闭的,这让我很烦,所以我更新了它以适合这个问题。嘿,已经4年了。大声笑
    • @MichaelDJohnson 无法解决上述问题,我们需要设置适当的时间戳,否则结果将不符合预期。
    【解决方案3】:

    我们遇到了与数据库中重复数据有关的问题,日期字段有多个值,而我们本来应该有 1 个值。我想我应该添加解决问题的方法以供参考。

    我们有一个名为“数据”的集合,其中包含一个数字“值”字段和一个日期“日期”字段。我们有一个我们认为是幂等的过程,但最终在第二次运行时每天添加 2 x 值:

    { "_id" : "1", "type":"x", "value":1.23, date : ISODate("2013-05-21T08:00:00Z")}
    { "_id" : "2", "type":"x", "value":1.23, date : ISODate("2013-05-21T17:00:00Z")}
    

    我们只需要 2 条记录中的 1 条,因此不得不使用 javascript 来清理数据库。我们最初的方法是遍历结果并删除时间在早上 6 点到 11 点之间的任何字段(所有重复项都在早上),但在实施过程中进行了更改。这是用于修复它的脚本:

    var data = db.data.find({"type" : "x"})
    var found = [];
    while (data.hasNext()){
        var datum = data.next();
        var rdate = datum.date;
        // instead of the next set of conditions, we could have just used rdate.getHour() and checked if it was in the morning, but this approach was slightly better...
        if (typeof found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] !== "undefined") {
           if (datum.value != found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()]) {
               print("DISCREPENCY!!!: " + datum._id + " for date " + datum.date);
           }
           else {
               print("Removing " + datum._id);
               db.data.remove({ "_id": datum._id});
           }
        }
        else {
           found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] = datum.value;
        }
    }
    

    然后用mongo thedatabase fixer_script.js运行它

    【讨论】:

      【解决方案4】:

      是的,Date 对象包含日期和时间,因此仅将其与日期值进行比较是行不通的。

      您可以简单地使用$where 运算符来用 Javascript 布尔表达式表达更复杂的条件:)

      db.posts.find({ '$where': 'this.created_on.toJSON().slice(0, 10) == "2012-07-14"' })
      

      created_on 是日期时间字段,2012-07-14 是指定日期。

      日期应完全采用 YYYY-MM-DD 格式。

      注意:谨慎使用$where,它会影响性能。

      【讨论】:

      • 我已经使用了你的答案,它给出了错误 $where not allowed in this atlas tier 如何解决?
      【解决方案5】:

      ...5 年后,我强烈建议改用 date-fns

      import endOfDayfrom 'date-fns/endOfDay'
      import startOfDay from 'date-fns/startOfDay'
      
      MyModel.find({
        createdAt: {
          $gte: startOfDay(new Date()),
          $lte: endOfDay(new Date())
        }
      })
      

      对于我们这些使用 Moment.js 的人

      const moment = require('moment')
      
      const today = moment().startOf('day')
      
      MyModel.find({
        createdAt: {
          $gte: today.toDate(),
          $lte: moment(today).endOf('day').toDate()
        }
      })
      

      重要提示:all moments are mutable!

      tomorrow = today.add(1, 'days') 不起作用,因为它也会变异 today。调用moment(today) 通过隐式克隆today 解决了这个问题。

      【讨论】:

      • 我建议使用.startOf('day') 而不是.hours(0).minutes(0).seconds(0)。所以第一行是:var today = moment().startOf('day')
      • 如果我们使用moment(today)来克隆对象,另一种解决方案是:var tomorrow = today.clone().add(1, 'days')
      • @johntellsall 显式克隆而不是隐式克隆,结果相同但确实更易于阅读!
      • 或者,我可以为$lt 建议以下内容:moment(today).endOf('day')。以防止包含第二天的实际结果。
      • 对我来说moment(today).endOf('day') 给出了与时间相同的日期:23:59:59.999。所以实际上使用$lte 看起来更正确,否则该特定时间的对象将被忽略。
      【解决方案6】:

      您可以使用以下 API 方法获取特定日期的结果:

      # [HTTP GET]
      getMeals: (req, res) ->
        options = {}
        # eg. api/v1/meals?date=Tue+Jan+13+2015+00%3A00%3A00+GMT%2B0100+(CET)
        if req.query.date?
          date = new Date req.query.date
          date.setHours 0, 0, 0, 0
          endDate = new Date date
          endDate.setHours 23, 59, 59, 59
          options.date =
            $lt: endDate
            $gte: date
      
        Meal.find options, (err, meals) ->
            if err or not meals
              handleError err, meals, res
            else
              res.json createJSON meals, null, 'meals'
      

      【讨论】:

        【解决方案7】:

        似乎没有一个答案对我有用。虽然有人提到了一点提示,但我设法使它与下面的代码一起工作。

        let endDate = startingDate
        endDate = endDate + 'T23:59:59';
        
        Model.find({dateCreated: {$gte: startingDate, $lte: endDate}})
        

        startingDate 将是您要查询的具体日期。

        我更喜欢这个解决方案以避免安装moment,而只是像"2021-04-01"那样在邮递员中传递startingDate

        【讨论】:

          【解决方案8】:

          下面给出了一个非常简单的解决方案

          const start = new Date(2020-04-01);
          start.setHours(0, 0, 0, 0);
          const end = new Date(2021-04-01);
          end.setHours(23, 59, 59, 999);
          queryFilter.created_at={
              $gte:start,
              $lte:end
          }
          YourModel.find(queryFilter)
          

          因此,上面的代码只是查找从给定开始日期到给定结束日期的记录。

          【讨论】:

            【解决方案9】:

            我用这种方法做的,效果很好

              public async getDatabaseorderbyDate(req: Request, res: Response) {
                const { dateQuery }: any = req.query
                const date = new Date(dateQuery)
                console.log(date)
                const today = date.toLocaleDateString(`fr-CA`).split('/').join('-')
                console.log(today)
                const creationDate = {
                  "creationDate": {
                    '$gte': `${today}T00:00:00.000Z`,
                    '$lt': `${today}T23:59:59.999Z`
                  }
                };
            
            `
            ``
            

            【讨论】:

              【解决方案10】:

              我遇到的问题是在后端过滤日期,当在节点服务器中将日期设置为 0 小时、0 分钟、0 秒、0 毫秒时,它在 ISO 时间中执行,因此当前日期为 0 小时、0 分钟、0 秒、0 毫秒客户的数量可能会有所不同,即,由于 ISO 时间到本地时区的转换,结果可能会在之后或之前给出一天

              我通过将本地时间从客户端发送到服务器来修复这些问题

               // If client is from Asia/Kathmandu timezone it will zero time in that zone.
              // Note ISODate time with zero time is not equal to above mention
              const timeFromClient = new Date(new Date().setHours(0,0,0,0)).getTime()
              

              并利用这段时间通过这个查询过滤文档

              const getDateQuery = (filterBy, time) => {
                  const today = new Date(time);
                  const tomorrow = new Date(today.getDate() + 1);
              
                  switch(filterBy) {
                      case 'past':
                          return {
                              $exists: true,
                              $lt: today,
                          };
                      case 'present': 
                          return {
                              $exists: true,
                              $gte: today,
                              $lt: tomorrow
                          };
                      case 'future':
                          return {
                              $exists: true,
                              $gte: tomorrow
                          };
                      default: 
                          return {
                              $exists: true
                          };
                  };
              };
              const users = await UserModel.find({
                  expiryDate: getDateQuery('past', timeFromClient)
              })
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-01-03
                • 2021-07-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-09-25
                • 2021-01-02
                相关资源
                最近更新 更多