Запит дати з 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 (), який повертає поточну дату у вигляді рядка.
  • новий конструктор Date (), який повертає об'єкт Date за допомогою обгортки ISODate ().
  • Конструктор ISODate (), який повертає об'єкт Date за допомогою обгортки ISODate ().

а використання ISODate все одно має повернути об'єкт Date .

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


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

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

@MattMolnar Помітив, і відповідь оновив атрибуцією. Дякую.
нуль323

92

З коментарів на сторінці кулінарної книги MongoDB :

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

Це працювало для мене. У повному контексті наступна команда отримує кожен запис, де в dtполі дати є дата зулулу 2013-10-01 (РРРР-ММ-DD):

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

1
Я отримав помилку "невизначена ISODate". Я не міг вирішити цю проблему.
Батухан Аккая

@BatuhanAkkaya У пітоні з пімонго datetime.datetimeеквівалентний ISODate.
jtbr


5

Я використовую robomongo в якості gui клієнта mongodb, і наведене нижче працює для мене

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

Що стосується додатку, я використовую драйвер mongodb на основі nodejs (v1.4.3), програма використовує підбірник дат у користувальницькому інтерфейсі, який дає дату, як YYYY-mm-dd, після чого додається із замовчуванням, як 00:00:00 до new Date()конструктора, а потім постачається до об'єкта критеріїв mongodb, я думаю, що драйвер перетворює дату в дату ISO, а потім запит працює і дає бажаний вихід, однак той же new Date()конструктор не працює і не показує однаковий вихід на robo mongo, для одного і того ж критерії, що дивно, оскільки я використовував робомонго для перехрещення перевірки своїх об'єктів критеріїв.

Тоді як за замовчуванням cli mongoshell добре працює з обома ISODateтаnew Date()


1
Дякую за пораду, Робомонго набагато кращий за компас Монго
Алекс

5

У суворому режимі json вам доведеться дотримуватися порядку:

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

Єдине, що допомогло визначити мої пошукові запити на mlab.com.


Помилка запуску запиту. Причина: (invalid_operator) Недійсний оператор: $ date
saber 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

Старе питання, але все-таки перший хіт Google, тому я публікую його тут, щоб я знову легше знаходив його ...

Використовуючи Mongo 4.2 та агрегат ():

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.