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!

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.


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

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

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


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.


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


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.


0

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

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


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.