MongoDB сравнивает даты только раз

Как мне запросить поле даты в MongoDB только с датой, а не раз? Например, если MongoDB хранит 7 июля 2015 года в любое время, я хочу сопоставить этот день только с сегодняшней датой.

В MySQL я бы сделал SELECT col1, col2 FROM table WHERE DATE(date_field) = DATE(NOW());

Обратите внимание, что MySQL имеет функцию изменения поля date_ date на дату только во время сопоставления. Могу ли я сделать это в MongoDB с аналогичной функцией во время сопоставления? Как Collection.find({ dateonly(datetimefield): dateonly(new Date() }); или что-то подобное?

Я понимаю, что Mongo хранит дату/время в GMT, поэтому мне также нужно будет преобразовать сохраненную дату GMT + время с GMT на локальный, прежде чем сопоставлять только дату, но чтобы начать меня, хотелось бы знать, могу ли я удалить время окончания матча даты. Например, если GMT сейчас - 8 июля в 03:00, но в "Местном восточном времени" США 7 июля в 23:00, я хотел бы соответствовать 7 июля.

Ответ 1

Обновлено 2018-06-26 Исправлен код для использования момента() вместо новой даты()

Похоже, что mongodb не эквивалентен функции MySQL DATE, как с SELECT col1, col2 FROM table WHERE DATE(date_field) = DATE(NOW())

Вместо нативного решения я решил эту проблему, используя MomentJS Timezone (http://momentjs.com/timezone/), чтобы преобразовать дату/время в числовое поле только для даты, затем я сохраняю дату как число.

В моем коде JavaScript (за пределами MongoDB):

var localDateOnly = function(timezone, d) {
  if (d == undefined) { d = new Date(); } // current date/time
  return Number( moment(d).tz(timezone).format("YYYYMMDD") );
}

Затем я сохраняю поле только для даты в записи Mongo.

var myDate = localDateOnly("America/New_York");  // today, in YYYYMMDD number
db.birthdays.insert(
  { dateonly: myDate, event: "This day is my birthday!" }
);

Затем в своем коде Javascript я могу легко запросить сегодня, завтра, в определенные дни и т.д.

// today
var myDate = localDateOnly("America/New_York");
db.birthdays.find( { dateonly: myDate } );

// tomorrow
var myDate = localDateOnly(
  "America/New_York",
  moment().add( 1, "days" )
);  // tomorrow
db.birthdays.find( { dateonly: myDate } );

// someone wants to know birthdays on the calendar on July 15, 2015
// regardless which time zone they are in
// just find the date in YYYYMMDD format
db.birthdays.find( { dateonly: 20150715 } );

Надеюсь, это кому-нибудь поможет. Он хранит число, а не строку, чтобы улучшить производительность своего индекса. У меня есть другой код, который вводит корректно выглядящий номер, прежде чем сохранить в базе данных, он проверяет:

moment( 20150715, "YYYYMMDD", true ).isValid()  // returns true & allowed to store in the database
moment( 150715, "YYYYMMDD", true ).isValid()  // returns false, don't insert into db

Ответ 2

Я думаю, вы должны сделать запрос диапазона между началом дня и его окончанием (или без окончания, если вы говорите о сегодняшнем дне). Что-то вроде этого

db.collection.find({
  "date" : {"$gte": new Date("2015-07-07T00:00:00.000Z"),
            "$lt": new Date("2015-07-08T00:00:00.000Z")}
})

Ответ 3

Это мое предлагаемое решение:

db.collection.find({
  $and: [
  {"date": {$gte: new Date("2015-07-07T00:00:00.000Z")}},
  {"date": {$lt: new Date("2015-07-08T00:00:00.000Z")}}
  ]
})

Ответ 4

Я сделал комбинацию ответов Crash_Override и Maxim_PontyUshenko. Используйте Moment.js и операторы $gt, $lt mongo.

ship_date: {
  $lt: moment().hours(0).minutes(0).seconds(0).milliseconds(0).add(28, "days").toDate(),
  $gte: moment().hours(0).minutes(0).seconds(0).milliseconds(0).toDate()
}

Ответ 5

Вы можете извлечь дату в виде строки в любом заданном формате и сравнить ее с вашей датой в этом формате, используя агрегированный пипилин

$addFields: { "creationDate":  {$dateToString:{format: "%Y-%m-%d", date: "$createdAt"}}}},
{$match :  { creationDate:  {$eq: req.query.date}}