La query sulla data con ISODate in mongodb non sembra funzionare


189

Non riesco a far funzionare anche la query di data più semplice per funzionare in MongoDB. Con un documento che assomiglia a questo:

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

E una query simile a questa:

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

Ottengo 0 risultati dall'esecuzione:

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

Qualche idea sul perché questo non funziona?

Per riferimento, questa query viene prodotta da MongoTemplate di Spring, quindi non ho il controllo diretto sulla query che viene infine inviata a MongoDB.

(PS)

> db.version()
2.4.7

Grazie!

Risposte:


312

Anche se $datefa parte di MongoDB Extended JSON ed è quello che ottieni come predefinito con mongoexportNon penso che puoi davvero usarlo come parte della query.

Se prova la ricerca esatta con $datecome di seguito:

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

otterrai errore:

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

Prova questo:

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

o (a seguito dei commenti di @ user3805045 ):

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

ISODatepotrebbe anche essere necessario confrontare le date senza tempo (indicato da @MattMolnar ).

Secondo i tipi di dati nella shell mongo entrambi dovrebbero essere equivalenti:

La shell mongo fornisce vari metodi per restituire la data, sia come stringa che come oggetto Date:

  • Metodo Date () che restituisce la data corrente come stringa.
  • nuovo costruttore Date () che restituisce un oggetto Date utilizzando il wrapper ISODate ().
  • Costruttore ISODate () che restituisce un oggetto Date utilizzando il wrapper ISODate ().

e l'utilizzo ISODate dovrebbe comunque restituire un oggetto Date .

{"$date": "ISO-8601 string"}può essere utilizzato quando è richiesta una rappresentazione JSON rigorosa. Un possibile esempio è il connettore Hadoop.


3
Si. Penso di essere stato respinto da ciò che viene restituito quando stampi l' Queryoggetto in primavera. La forma serializzata della query non è necessariamente una query valida che puoi semplicemente copiare / incollare in una shell mongo, che di per sé è frustrante. Il colpevole è qui: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
Jason

2
Quando ho confrontato una data parziale (senza orario), ho dovuto passare da new Date('2016-03-09')a ISODate('2016-03-09'). Il primo restituiva le date nel passato per una $gtequery.
Matt Molnar,

@MattMolnar Noted e ha aggiornato la risposta con un'attribuzione. Grazie.
zero323

92

Dai commenti sulla pagina del ricettario MongoDB :

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

Questo ha funzionato per me. Nel contesto completo, il comando seguente ottiene tutti i record in cui il dtcampo della data ha una data su 2013-10-01 (AAAA-MM-GG) Zulu:

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

1
Ho ricevuto un errore "ISODate non definito". Non sono riuscito a risolvere questo problema.
Batuhan Akkaya,

@BatuhanAkkaya In pitone con pymongo, datetime.datetimeequivale a ISODate.
jtbr

12

Prova questo:

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

5

Sto usando robomongo come gui client mongodb e il seguito ha funzionato per me

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

Sul lato app sto usando il driver mongodb basato su nodejs (v1.4.3), l'applicazione usa datepicker nell'interfaccia utente che fornisce una data come AAAA-mm-gg, che viene quindi aggiunta con un tempo predefinito come 00:00:00 e quindi data al new Date()costruttore e quindi fornito all'oggetto criteri mongodb, penso che il driver converta la data in data ISO e la query quindi new Date()funzioni e fornisce l'output desiderato, tuttavia lo stesso costruttore non funziona o mostra lo stesso output su robo mongo, per lo stesso criteri, il che è strano, dal momento che ho usato robomongo per controllare i miei oggetti criteri.

Considerando che il cli mongoshell predefinito funziona bene con entrambi ISODateenew Date()


1
Grazie per la punta, Robomongo è molto meglio di Mongo Compass
Alex

5

In modalità rigorosa json, dovrai mantenere l'ordine:

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

L'unica cosa che ha funzionato per definire le mie query di ricerca su mlab.com.


Errore durante l'esecuzione della query. Motivo: (invalid_operator) Operatore non valido: $ date
sabre tabatabaee yazdi

2

Nella shell MongoDB:

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

Nel mio codice nodeSJ (usando Mongoose)

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

Sto interrogando la mia raccolta di eventi del sensore per restituire valori in cui il campo 'da' è maggiore della data specificata


4
Benvenuto in Stack Overflow! Pubblica semplicemente la risposta alla domanda e non cose extra come "Questo è il mio primo post". Pensa a Stack Overflow come a Wikipedia, non a una bacheca.
durron597,

1

questo è il mio documento

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

ora voglio trovare ogni 27 ° documento dat.so ho usato questo ....

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

result:1

questo ha funzionato per me.


0

Questo ha funzionato per me mentre cercavo un valore inferiore o uguale a quello attuale:

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

0

Avvolgilo con new Date():

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

0

Vecchia domanda, ma comunque primo colpo di google, quindi lo pubblico qui in modo da trovarlo di nuovo più facilmente ...

Usando Mongo 4.2 e un aggregato ():

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

Questo ti dà la variabile groupby come una data, a volte meglio gestire i componenti stessi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.