La consulta de fecha con ISODate en mongodb no parece funcionar

189

Parece que no puedo obtener ni siquiera la consulta de fecha más básica para trabajar en MongoDB. Con un documento que se parece a esto:

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

Y una consulta que se ve así:

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

Obtengo 0 resultados de la ejecución:

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

¿Alguna idea de por qué esto no funciona?

Como referencia, esta consulta está siendo producida por Spring's MongoTemplate, por lo que no tengo control directo sobre la consulta que finalmente se envía a MongoDB.

(PD)

> db.version()
2.4.7

¡Gracias!

Jason Polites
fuente

Respuestas:

312

Aunque $datees parte de MongoDB Extended JSON y eso es lo que obtienes por defecto mongoexport, no creo que realmente puedas usarlo como parte de la consulta.

Si intenta una búsqueda exacta con el $datesiguiente:

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

obtendrás un error:

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

Prueba esto:

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

o (siguiendo los comentarios de @ user3805045 ):

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

ISODatetambién puede ser necesario para comparar fechas sin tiempo (anotado por @MattMolnar ).

Según los tipos de datos en el shell mongo, ambos deberían ser equivalentes:

El shell mongo proporciona varios métodos para devolver la fecha, ya sea como una cadena o como un objeto Date:

  • Método Date () que devuelve la fecha actual como una cadena.
  • nuevo constructor Date () que devuelve un objeto Date utilizando el contenedor ISODate ().
  • El constructor ISODate () que devuelve un objeto Date utilizando el contenedor ISODate ().

y el uso ISODate aún debe devolver un objeto Date .

{"$date": "ISO-8601 string"}se puede usar cuando se requiere una representación JSON estricta. Un posible ejemplo es el conector Hadoop.

cero323
fuente
3
Si. Creo que me sorprendió lo que se devuelve cuando imprime el Queryobjeto en Spring. La forma serializada de la consulta no es necesariamente una consulta válida que solo puede copiar / pegar en un shell de mongo, lo que en sí mismo es algo frustrante. El culpable está aquí: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
Jason Polites el
2
Al comparar una fecha parcial (sin hora), tuve que cambiar de new Date('2016-03-09')a ISODate('2016-03-09'). El primero devolvería fechas en el pasado para una $gteconsulta.
Matt Molnar
@MattMolnar tomó nota y actualizó la respuesta con una atribución. Gracias.
zero323
92

De los comentarios de la página del libro de cocina MongoDB :

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

Esto funcionó para mí. En un contexto completo, el siguiente comando obtiene todos los registros donde el dtcampo de fecha tiene una fecha en 2013-10-01 (AAAA-MM-DD) Zulu:

db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})
Steve HHH
fuente
1
Recibí un error "ISODate undefined". No pude resolver este problema.
Batuhan Akkaya
@BatuhanAkkaya En python con pymongo, datetime.datetimees equivalente a ISODate.
jtbr
12

Prueba esto:

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

Estoy usando robomongo como la interfaz de usuario del cliente mongodb y lo siguiente funcionó para mí

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

En el lado de la aplicación, estoy usando el controlador mongodb basado en nodejs (v1.4.3), la aplicación usa datepicker en la interfaz de usuario que da una fecha como AAAA-mm-dd, esto se agrega con un tiempo predeterminado como 00:00:00 y luego se da para el new Date()constructor y luego suministrado al objeto de criterios mongodb, creo que el controlador convierte la fecha a la fecha ISO y la consulta funciona y proporciona el resultado deseado, sin embargo, el mismonew Date() constructor no funciona o muestra la misma salida en robo mongo, para el mismo criterio, lo cual es extraño, ya que usé robomongo para verificar mis objetos de criterio.

Mientras que el cli mongoshell predeterminado funciona bien con ambos ISODateynew Date()

siddharthrc
fuente
1
Gracias por el consejo, Robomongo es mucho mejor que Mongo Compass
Alex
5

En el modo estricto json, deberá mantener el orden:

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

Lo único que funcionó para definir mis consultas de búsqueda en mlab.com.

3vangelos
fuente
Error al ejecutar la consulta. Motivo: (operador_válido) Operador no válido: $ fecha
sable tabatabaee yazdi
2

En el shell MongoDB:

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

En mi código nodeJS (usando Mongoose)

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

Estoy consultando mi colección de eventos del sensor para devolver valores donde el campo 'desde' es mayor que la fecha dada

lewma
fuente
44
¡Bienvenido a Stack Overflow! Simplemente publique la respuesta a la pregunta, y no cosas adicionales como "Esta es mi primera publicación". Piense en Stack Overflow como Wikipedia, no como un tablero de mensajes.
durron597
1

este es mi 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",

ahora quiero encontrar cada documento de fecha 27, así que usé esto ...

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

result:1

Esto funcionó para mí.

descifrador
fuente
0

Esto funcionó para mí mientras buscaba un valor menor o igual que ahora:

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

Envuélvelo con new Date():

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

Antigua pregunta, pero aún así es el primer hit de Google, así que lo publico aquí, así que lo encuentro de nuevo más fácilmente ...

Usando Mongo 4.2 y un agregado ():

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

Este le da la variable groupby como una fecha, a veces mejor para manejar como los componentes en sí.

A. Rabus
fuente