Запрос даты с ISODate в mongodb не работает

102

Я, похоже, не могу получить даже самый базовый запрос даты для работы в MongoDB. С документом, который выглядит примерно так:

{
    "_id" : "foobar/201310",
    "ap" : "foobar",
    "dt" : ISODate("2013-10-01T00:00:00.000Z"),
    "tl" : 375439
}

И запрос выглядит следующим образом:

{ 
    "dt" : { 
        "$gte" : { 
            "$date" : "2013-10-01T00:00:00.000Z"
        }
    }
}

Я получаю 0 результатов от выполнения:

db.mycollection.find({
  "dt" : { "$gte" : { "$date" : "2013-10-01T00:00:00.000Z"}}
})

Любая идея, почему это не работает?

Для справки этот запрос создается Spring MongoTemplate, поэтому я не имею прямого контроля над запросом, который в конечном итоге отправлен к MongoDB.

(P.S.)

> db.version()
2.4.7

Спасибо!

Теги:
isodate
bson

7 ответов

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

Хотя $date является частью MongoDB Extended JSON и что вы получаете по умолчанию с mongoexport Я не думаю, что вы может действительно использовать его как часть запроса.

Если попробуйте выполнить точный поиск с помощью $date, как показано ниже:

db.foo.find({dt: {"$date": "2012-01-01T15:00:00.000Z"}})

вы получите сообщение об ошибке:

error: { "$err" : "invalid operator: $date", "code" : 10068 }

Попробуйте следующее:

db.mycollection.find({
    "dt" : {"$gte": new Date("2013-10-01T00:00:00.000Z")}
})

или (следующие комментарии @user3805045):

db.mycollection.find({
    "dt" : {"$gte": ISODate("2013-10-01T00:00:00.000Z")}
})

ISODate также может потребоваться для сравнения дат без времени (отмечено @MattMolnar).

Согласно Типы данных в оболочке mongo должны быть эквивалентными:

В оболочке mongo предусмотрены различные методы для возврата даты либо в виде строки, либо как объект Date:

  • Метод Date(), который возвращает текущую дату в виде строки.
  • новый конструктор Date(), который возвращает объект Date с помощью оболочки ISODate().Конструктор
  • ISODate(), который возвращает объект Date с помощью оболочки ISODate().

и используя ISODate должен по-прежнему возвращать объект Date.

{"$date": "ISO-8601 string"} может использоваться, когда требуется строгое представление JSON. Одним из возможных примеров является разъем Hadoop.

  • 2
    Да уж. Я думаю, что я был сбит с толку тем, что возвращается, когда вы распечатываете объект Query в Spring. Сериализованная форма запроса не обязательно является допустимым запросом, который вы можете просто скопировать / вставить в оболочку mongo, что само по себе несколько расстраивает. Виновник здесь: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
  • 2
    При сравнении частичной (без времени) даты мне пришлось переключиться с new Date('2016-03-09') на ISODate('2016-03-09') . Первый возвращает даты в прошлом для запроса $gte .
Показать ещё 1 комментарий
63

Из комментариев по электронной почте MongoDB:

"dt" : 
{
    "$gte" : ISODate("2014-07-02T00:00:00Z"), 
    "$lt" : ISODate("2014-07-03T00:00:00Z") 
}

Это сработало для меня. В полном контексте следующая команда получает каждую запись, где поле даты dt имеет дату 2013-10-01 (ГГГГ-ММ-ДД) Зулу:

db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})
  • 0
    Я получил ошибку "ISODate undefined". Я не мог решить эту проблему.
  • 0
    @BatuhanAkkaya В python с pymongo datetime.datetime эквивалентно ISODate .
7

Попробуйте следующее:

{ "dt" : { "$gte" : ISODate("2013-10-01") } }
5

В строгом режиме json вам нужно сохранить порядок:

{
    "dt": {
        "$gte": {
            "$date": "2013-10-01T00:00:00.000Z"
        }
    }
}

Единственное, что сработало для определения моих поисковых запросов на mlab.com.

  • 0
    Ошибка при выполнении запроса. Причина: (invalid_operator) Недопустимый оператор: $ date
3

Я использую robomongo как клиент gui mongodb, и ниже работал у меня

db.collectionName.find({"columnWithDateTime" : {
$lt:new ISODate("2016-02-28T00:00:00.000Z")}})

На стороне приложения я использую драйвер на основе nodejs mongodb (v1.4.3), приложение использует datepicker в ui, который дает дату, например, YYYY-mm-dd, после чего добавляется по умолчанию, например 00:00:00 а затем передается конструктору new Date() и затем передается объекту критериев mongodb, я думаю, что драйвер преобразует дату в дату ISO, и затем запрос работает и дает желаемый результат, однако тот же конструктор new Date() не работает или не показывает тот же вывод на robo mongo, по тем же критериям, что и странно, поскольку я использовал robomongo для перекрестного проверки объектов моих критериев.

В то время как по умолчанию cli mongoshell хорошо работает как с ISODate, так и с new Date()

  • 0
    Спасибо за совет, Robomongo намного лучше, чем Mongo Compass
2

В оболочке MongoDB:

db.getCollection('sensorevents').find({from:{$gt: new ISODate('2015-08-30 16:50:24.481Z')}})

В моем nodeJS-коде (с использованием Mongoose)

    SensorEvent.Model.find( {
        from: { $gt: new Date( SensorEventListener.lastSeenSensorFrom ) }
    } )

Я запрашиваю мой сбор событий событий, чтобы возвращать значения, где поле "from" больше заданной даты

  • 3
    Добро пожаловать в переполнение стека! Пожалуйста, просто опубликуйте ответ на вопрос, а не дополнительные материалы, такие как «Это мой первый пост». Думайте о переполнении стека как о Википедии, а не о доске объявлений.
1

это мой документ

"_id" : ObjectId("590173023c488e9a48e903d6"),
    "updatedAt" : ISODate("2017-04-27T04:26:42.709Z"),
    "createdAt" : ISODate("2017-04-27T04:26:42.709Z"),
    "flightId" : "590170f97cb84116075e2680",

 "_id" : ObjectId("590173023c488e9a48e903d6"),
        "updatedAt" : ISODate("2017-04-28T03:26:42.609Z"),
        "createdAt" : ISODate("2017-04-28T03:26:42.609Z"),
        "flightId" : "590170f97cb84116075e2680",

теперь я хочу найти каждый 27-й документ date.so, я использовал это....

 > db.users.find({createdAt:{"$gte":ISODate("2017-04-27T00:00:00Z"),"$lt":ISODate("2017-04-28T00:00:00Z") }}).count()

result:1

это сработало для меня.

Ещё вопросы

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