Zapytanie o datę z ISODate w mongodb nie działa

189

Wydaje mi się, że nie jestem w stanie uzyskać nawet najbardziej podstawowego zapytania dotyczącego daty w MongoDB. Z dokumentem, który wygląda mniej więcej tak:

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

I zapytanie, które wygląda tak:

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

Otrzymuję 0 wyników z wykonania:

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

Wiesz, dlaczego to nie działa?

Dla porównania, zapytanie to jest tworzone przez MongoTemplate Springa więc nie mam bezpośredniej kontroli nad zapytaniem, które ostatecznie jest wysyłane do MongoDB.

(PS)

> db.version()
2.4.7

Dzięki!

Jason Polites
źródło

Odpowiedzi:

312

Chociaż $datejest częścią rozszerzonego JSON MongoDB i to jest to, co dostajesz domyślnie mongoexport, nie sądzę, abyś mógł naprawdę użyć go jako części zapytania.

Jeśli spróbuj dokładnego wyszukiwania, na $dateprzykład poniżej:

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

dostaniesz błąd:

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

Spróbuj tego:

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

lub (następujące komentarze @ user3805045 ):

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

ISODatemoże być również wymagane porównanie dat bez czasu (odnotowane przez @MattMolnar ).

Zgodnie z typami danych w powłoce mangowej oba powinny być równoważne:

Powłoka mongo udostępnia różne metody zwracania daty, jako ciąg znaków lub obiekt Date:

  • Metoda date (), która zwraca bieżącą datę jako ciąg.
  • nowy konstruktor Date (), który zwraca obiekt Date za pomocą opakowania ISODate ().
  • Konstruktor ISODate (), który zwraca obiekt Date za pomocą opakowania ISODate ().

i używanie ISODate powinno nadal zwracać obiekt Date .

{"$date": "ISO-8601 string"}można użyć, gdy wymagana jest ścisła reprezentacja JSON. Jednym z możliwych przykładów jest złącze Hadoop.

zero323
źródło
3
Tak. Myślę, że mnie zaskoczyło to, co zostało zwrócone, kiedy wydrukowałeś Queryobiekt wiosną. Serializowana forma zapytania niekoniecznie jest poprawnym zapytaniem, które można po prostu skopiować / wkleić do powłoki mongo, co samo w sobie jest frustrujące. Sprawca
Jason Polites
2
Porównując częściową (bez godziny) datę, musiałem zmienić z new Date('2016-03-09')na ISODate('2016-03-09'). Ten pierwszy zwróciłby daty w przeszłości dla $gtezapytania.
Matt Molnar,
@MattMolnar Zauważył i zaktualizował odpowiedź z podaniem źródła. Dzięki.
zero323
92

Z MongoDB Cookbook stronie komentarzy:

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

To zadziałało dla mnie. W pełnym kontekście następujące polecenie pobiera każdy rekord, w którym dtpole daty ma datę w dniu Zulu 2013-10-01 (RRRR-MM-DD):

db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})
Steve HHH
źródło
1
Wystąpił błąd „Nieokreślony ISODate”. Nie mogłem rozwiązać tego problemu.
Batuhan Akkaya,
@BatuhanAkkaya W python z pymongo datetime.datetimejest równoważne ISODate.
jtbr
12

Spróbuj tego:

{ "dt" : { "$gte" : ISODate("2013-10-01") } }
Jabba
źródło
5

Używam robomongo jako GUI klienta mongodb i poniższe działały dla mnie

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

Po stronie aplikacji używam sterownika mongodb opartego na nodejs (v1.4.3), aplikacja używa datepicker w interfejsie użytkownika, który podaje datę jak RRRR-mm-dd, następnie jest dodawany z domyślnym czasem jak 00:00:00, a następnie podawany do new Date()konstruktora, a następnie dostarczony do obiektu kryteriów mongodb, myślę, że sterownik konwertuje datę na datę ISO, a następnie zapytanie działa i daje pożądane dane wyjściowe, jednak takie samenew Date() konstruktor nie działa lub wyświetla takie same dane wyjściowe w robo mongo, dla tego samego kryteria, co jest dziwne, ponieważ użyłem robomongo do sprawdzenia krzyżowego obiektów kryteriów.

Podczas gdy domyślna mlioshell cli działa dobrze zarówno z, jak ISODateinew Date()

siddharthrc
źródło
1
Dziękujemy za wskazówkę, Robomongo jest znacznie lepszy niż Mongo Compass
Alex
5

W trybie ścisłym Json musisz zachować kolejność:

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

Jedyne, co zadziałało, aby zdefiniować moje zapytania w mlab.com.

3vangelos
źródło
Błąd uruchamiania zapytania. Powód: (invalid_operator) Niepoprawny operator: $ date
sabre tabatabaee yazdi
2

W powłoce MongoDB:

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

W moim węźle kod JS (za pomocą Mongoose)

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

Pytam moją kolekcję zdarzeń czujnika, aby zwrócić wartości, w których pole „z” jest większe niż podana data

lewma
źródło
4
Witamy w Stack Overflow! Proszę po prostu opublikować odpowiedź na pytanie, a nie dodatkowe rzeczy, takie jak „To jest mój pierwszy post”. Pomyśl o przepełnieniu stosu jak o Wikipedii, a nie o tablicy ogłoszeń.
durron597,
1

to jest mój 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",

teraz chcę znaleźć dokument z 27 datą. więc użyłem tego ....

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

result:1

to zadziałało dla mnie.

koder
źródło
0

To działało dla mnie podczas wyszukiwania wartości mniejszej lub równej niż teraz:

db.collectionName.find({ "dt": { "$lte" : new Date() + "" } });
JulienRioux
źródło
0

Owiń to new Date():

{ "dt" : { "$lt" : new Date("2012-01-01T15:00:00.000Z") } }
Ehsan sarshar
źródło
0

Stare pytanie, ale wciąż pierwszy hit w Google, więc zamieszczam je tutaj, aby łatwiej je znaleźć ...

Korzystanie z Mongo 4.2 i agregacji ():

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

Ta daje ci zmienną groupby jako datę, czasem lepiej jest traktować ją jako same komponenty.

A. Rabus
źródło