Datumsabfrage mit ISODate in Mongodb scheint nicht zu funktionieren


189

Ich scheine nicht in der Lage zu sein, auch nur die grundlegendste Datumsabfrage in MongoDB zum Laufen zu bringen. Mit einem Dokument, das ungefähr so ​​aussieht:

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

Und eine Abfrage, die so aussieht:

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

Ich erhalte 0 Ergebnisse bei der Ausführung:

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

Irgendeine Idee, warum das nicht funktioniert?

Als Referenz wird diese Abfrage von MongoTemplate von Spring erstellt, sodass ich keine direkte Kontrolle über die Abfrage habe, die letztendlich an MongoDB gesendet wird.

(PS)

> db.version()
2.4.7

Vielen Dank!

Antworten:


312

Obwohl $datees Teil von MongoDB Extended JSON ist und das ist, was Sie standardmäßig erhalten, mongoexportglaube ich nicht, dass Sie es wirklich als Teil der Abfrage verwenden können.

Wenn Sie versuchen, genaue Suche mit $datewie folgt:

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

Sie erhalten eine Fehlermeldung:

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

Versuche dies:

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

oder (folgende Kommentare von @ user3805045 ):

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

ISODateMöglicherweise müssen Sie auch Daten ohne Zeitangabe vergleichen (von @MattMolnar notiert ).

Entsprechend den Datentypen in der Mongo-Shell sollten beide gleichwertig sein:

Die Mongo-Shell bietet verschiedene Methoden, um das Datum zurückzugeben, entweder als Zeichenfolge oder als Datumsobjekt:

  • Date () -Methode, die das aktuelle Datum als Zeichenfolge zurückgibt.
  • neuer Date () -Konstruktor, der ein Date-Objekt mit dem ISODate () -Wrapper zurückgibt.
  • ISODate () -Konstruktor, der mit dem ISODate () -Wrapper ein Date-Objekt zurückgibt.

und mit ISODate sollte weiterhin ein Date-Objekt zurückgeben .

{"$date": "ISO-8601 string"}kann verwendet werden, wenn eine strikte JSON-Darstellung erforderlich ist. Ein mögliches Beispiel ist der Hadoop-Anschluss.


3
Ja. Ich glaube, ich war beeindruckt von dem, was zurückgegeben wird, wenn Sie das QueryObjekt im Frühjahr ausdrucken . Die serialisierte Form der Abfrage ist nicht unbedingt eine gültige Abfrage, die Sie einfach kopieren / in eine Mongo-Shell einfügen können, was an sich schon frustrierend ist. Der Schuldige ist hier: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
Jason Polites

2
Wenn ein Teil (keine Zeit) Datum zu vergleichen, hatte ich von wechseln new Date('2016-03-09')zu ISODate('2016-03-09'). Ersteres würde Daten in der Vergangenheit für eine $gteAbfrage zurückgeben.
Matt Molnar

@MattMolnar Noted und aktualisiert die Antwort mit einer Zuschreibung. Vielen Dank.
Null323

92

Aus den Kommentaren der MongoDB-Kochbuchseite :

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

Das hat bei mir funktioniert. Im vollständigen Kontext dtruft der folgende Befehl jeden Datensatz ab, in dem das Datumsfeld ein Datum am 2013-10-01 (JJJJ-MM-TT) Zulu hat:

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

1
Ich habe den Fehler "ISODate undefined" erhalten. Ich konnte dieses Problem nicht lösen.
Batuhan Akkaya

@BatuhanAkkaya In Python mit Pymongo datetime.datetimeist gleichbedeutend mit ISODate.
jtbr

12

Versuche dies:

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

5

Ich benutze Robomongo als Mongodb-Client-GUI und das Folgende hat für mich funktioniert

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

Auf der App-Seite verwende ich den NodeJS-basierten Treiber Mongodb (v1.4.3). Die Anwendung verwendet einen Datepicker in der Benutzeroberfläche, der ein Datum wie JJJJ-MM-TT angibt. Dieses wird dann mit der Standardzeit wie 00:00:00 angehängt und dann angegeben an den new Date()Konstruktor und dann das Objekt an die mongodb Kriterien geliefert, ich glaube , die Treiber konvertiert das Datum nach ISO Datum und die Abfrage dann arbeitet und die gewünschte Ausgabe gibt, aber die gleichenew Date() tut Konstruktor keine Arbeit oder gleiche Leistung auf robo mongo zeigen, für die gleiche Kriterien, was seltsam ist, da ich Robomongo verwendet habe, um meine Kriterienobjekte zu überprüfen.

Während der Standard - cli mongoshell funktioniert gut mit den beiden ISODateundnew Date()


1
Vielen Dank für den Tipp, Robomongo ist viel besser als Mongo Compass
Alex

5

Im strengen json-Modus müssen Sie die Reihenfolge einhalten:

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

Einzige Sache, die funktioniert hat, um meine Suchanfragen auf mlab.com zu definieren.


Fehler beim Ausführen der Abfrage. Grund: (invalid_operator) Ungültiger Operator: $ date
saber tabatabaee yazdi

2

In der MongoDB-Shell:

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

In meinem nodeJS-Code (mit Mongoose)

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

Ich frage meine Sensorereignissammlung ab, um Werte zurückzugeben, bei denen das Feld "Von" größer als das angegebene Datum ist


4
Willkommen bei Stack Overflow! Bitte poste einfach die Antwort auf die Frage und keine zusätzlichen Dinge wie "Dies ist mein erster Beitrag". Stellen Sie sich Stack Overflow als Wikipedia vor, nicht als Message Board.
Durron597

1

Das ist mein Dokument

"_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",

Jetzt möchte ich jedes Dokument mit dem 27. Datum finden. Also habe ich dieses verwendet ....

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

result:1

das hat bei mir funktioniert.


0

Dies funktionierte für mich bei der Suche nach einem Wert, der kleiner oder gleich als jetzt ist:

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

0

Wickeln Sie es ein mit new Date():

{ "dt" : { "$lt" : new Date("2012-01-01T15:00:00.000Z") } }

0

Alte Frage, aber immer noch der erste Google-Hit, also poste ich ihn hier, damit ich ihn leichter wieder finde ...

Verwenden von Mongo 4.2 und einem Aggregat ():

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

Diese gibt Ihnen die Variable groupby als Datum, manchmal besser als die Komponenten selbst.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.