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


189

Кажется, я не могу заставить даже самый простой запрос даты работать в 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"}}
})

Есть идеи, почему это не работает?

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

(PS)

> db.version()
2.4.7

Спасибо!

Ответы:


312

Хотя $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 предоставляет различные методы для возврата даты в виде строки или объекта Date:

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

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

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


3
Да. Я думаю, что я был сбит с толку тем, что возвращается, когда вы распечатываете Queryобъект весной. Сериализованная форма запроса не обязательно является допустимым запросом, который вы можете просто скопировать / вставить в оболочку mongo, что само по себе несколько расстраивает. Виновник здесь: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
Джейсон Политес

2
При сравнении частичной (без времени) даты мне пришлось переключиться с new Date('2016-03-09')на ISODate('2016-03-09'). Первый будет возвращать даты в прошлом для $gteзапроса.
Мэтт Молнар

@MattMolnar отметил, и обновил ответ с атрибуцией. Спасибо.
zero323

92

Со страницы кулинарной книги 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") }})

1
Я получил ошибку "ISODate undefined". Я не мог решить эту проблему.
Батухан Аккая

@BatuhanAkkaya В python с pymongo datetime.datetimeэквивалентно ISODate.
jtbr


5

Я использую robomongo в качестве клиентского интерфейса mongodb, и ниже работает для меня

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

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

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


1
Спасибо за подсказку, Robomongo намного лучше, чем Mongo Compass
Alex

5

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

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

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


Ошибка при выполнении запроса. Причина: (invalid_operator) Неверный оператор: $ date
сабля tabatabaee yazdi

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 ) }
    } )

Я запрашиваю мою коллекцию событий датчика, чтобы она возвращала значения, в которых поле «от» больше указанной даты


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

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-й документ даты. так что я использовал это ....

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

result:1

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


0

Это сработало для меня при поиске значения меньше или равно, чем сейчас:

db.collectionName.find({ "dt": { "$lte" : new Date() + "" } });


0

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

Используя Mongo 4.2 и aggregate ():

db.collection.aggregate(
    [
     { $match: { "end_time": { "$gt": ISODate("2020-01-01T00:00:00.000Z")  } } },
     { $project: {
          "end_day": { $dateFromParts: { 'year' : {$year:"$end_time"}, 'month' : {$month:"$end_time"}, 'day': {$dayOfMonth:"$end_time"}, 'hour' : 0  } }
     }}, 
     {$group:{
        _id:   "$end_day",
        "count":{$sum:1},
    }}
   ]
)

Это дает вам переменную groupby в качестве даты, иногда лучше использовать как компоненты.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.