MongoDB / Mongoose запрашивает на конкретную дату?

107

Можно ли запросить конкретную дату?

Я нашел в Поваренной книге монго, что мы можем сделать это для диапазона Запрос для диапазона дат Например:

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

Но возможно ли конкретная дата? Это не работает:

db.posts.find({"created_on": new Date(2012, 7, 14) })
Теги:
express
mongoose
odm

6 ответов

154
Лучший ответ

Это должно работать, если даты, которые вы сохранили в БД, не имеют времени (только год, месяц, день).

Скорее всего, даты, которые вы сохранили, были new Date(), который включает компоненты времени. Чтобы запросить это время, вам нужно создать диапазон дат, включающий все моменты дня.

db.posts.find( //query today up to tonight
  {"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})
  • 24
    Помните, что в функции Date () аргумент month начинается со значения 0, а не 1. С другой стороны, дни начинаются со значения 1 ... подробнее
  • 0
    не лучше ли сделать _ 1 день, чтобы получить следующую дату, а не жесткий код оба?
Показать ещё 2 комментария
83

Для тех из нас, кто использует Moment.js

const moment = require('moment')

const today = moment().startOf('day')

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

Важно: все моменты изменчивы !

tomorrow = today.add(1, 'days') не работает, так как он также мутирует today. Вызывающий moment(today) решает эту проблему путем неявного клонирования today.

  • 13
    Я предлагаю использовать .startOf('day') вместо .hours (0) .minutes (0) .seconds (0). Поэтому первая строка будет выглядеть так: var today = moment().startOf('day')
  • 0
    Ницца. Это сработало потрясающе!
Показать ещё 6 комментариев
6

Вы пробовали:

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

Проблема, с которой вы столкнетесь, заключается в том, что даты хранятся как отметки времени в Mongo. Итак, чтобы соответствовать дате, вы просите ее сопоставить временную метку. В вашем случае я думаю, что вы пытаетесь сопоставить день (т.е. С 00:00 до 23:59 в определенную дату). Если ваши даты хранятся без разницы, тогда вы должны быть в порядке. В противном случае попробуйте указать дату в качестве диапазона времени в тот же день (т.е. start = 00: 00, end = 23: 59), если gte не работает.

аналогичный вопрос

  • 1
    Это будет включать все элементы моложе указанной даты, что, вероятно, не то, что хотел ОП. Попробуйте добавить опцию «lt», как и другие ответы.
  • 0
    Я думаю, что если у вас есть $gte вместо gte было бы лучше.
Показать ещё 1 комментарий
5

Да, объект Date задает дату и время, поэтому сравнение его с только значением даты не работает.

Вы можете просто использовать оператор $where, чтобы выразить более сложное условие с помощью выражения Javascript boolean:)

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

created_on - это поле datetime, а 2012-07-14 - указанная дата.

Дата должна быть точно в формате ГГГГ-ММ-ДД.

Примечание. Используйте $where экономно, это имеет последствия для производительности.

4

Вы можете использовать следующий подход для метода 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'
0

У нас была проблема, связанная с дублированием данных в нашей базе данных, с полем даты, имеющим несколько значений, где мы должны были иметь 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")}

Нам нужно только 1 из 2 записей, поэтому пришлось прибегнуть к javascript, чтобы очистить db. Наш первоначальный подход состоял в том, чтобы перебирать результаты и удалять любое поле со временем между 6:00 и 11:00 (все дубликаты были утром), но во время реализации внесли изменения. Здесь script используется для его исправления:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню