2010-05-31 61 views
252

He estado jugando el almacenamiento de los tweets dentro mongodb, cada objeto tiene el siguiente aspecto:encontrar objetos entre dos fechas MongoDB

{ 
"_id" : ObjectId("4c02c58de500fe1be1000005"), 
"contributors" : null, 
"text" : "Hello world", 
"user" : { 
    "following" : null, 
    "followers_count" : 5, 
    "utc_offset" : null, 
    "location" : "", 
    "profile_text_color" : "000000", 
    "friends_count" : 11, 
    "profile_link_color" : "0000ff", 
    "verified" : false, 
    "protected" : false, 
    "url" : null, 
    "contributors_enabled" : false, 
    "created_at" : "Sun May 30 18:47:06 +0000 2010", 
    "geo_enabled" : false, 
    "profile_sidebar_border_color" : "87bc44", 
    "statuses_count" : 13, 
    "favourites_count" : 0, 
    "description" : "", 
    "notifications" : null, 
    "profile_background_tile" : false, 
    "lang" : "en", 
    "id" : 149978111, 
    "time_zone" : null, 
    "profile_sidebar_fill_color" : "e0ff92" 
}, 
"geo" : null, 
"coordinates" : null, 
"in_reply_to_user_id" : 149183152, 
"place" : null, 
"created_at" : "Sun May 30 20:07:35 +0000 2010", 
"source" : "web", 
"in_reply_to_status_id" : { 
    "floatApprox" : 15061797850 
}, 
"truncated" : false, 
"favorited" : false, 
"id" : { 
    "floatApprox" : 15061838001 
} 

¿cómo iba a escribir una consulta que comprueba el created_at y busca todos los objetos entre 18:47 y 19:00? ¿Debo actualizar mis documentos para que las fechas se almacenen en un formato específico?

+0

¿No dice sobre qué campo quiere consultar? – shingara

+0

Vaya, quiero consultar el created_at y buscar todo entre dos fechas. – Tom

+0

Tengo curiosidad por saber por qué no utilizar la marca de tiempo, cualquier ventaja con el uso de la Fecha Obj? – Leo

Respuesta

395

Querying for a Date Range (Specific Month or Day) en el MongoDB Cookbook tiene una muy buena explicación sobre el asunto, pero por debajo es algo que probé a mí mismo y parece que funciona.

items.save({ 
    name: "example", 
    created_at: ISODate("2010-04-30T00:00:00.000Z") 
}) 
items.find({ 
    created_at: { 
     $gte: ISODate("2010-04-29T00:00:00.000Z"), 
     $lt: ISODate("2010-05-01T00:00:00.000Z") 
    } 
}) 
=> { "_id" : ObjectId("4c0791e2b9ec877893f3363b"), "name" : "example", "created_at" : "Sun May 30 2010 00:00:00 GMT+0300 (EEST)" } 

Basado en mis experimentos que se necesitan para serializar las fechas en un formato que es compatible con MongoDB, debido a los siguientes dieron resultados deseados.

items.save({ 
    name: "example", 
    created_at: "Sun May 30 18.49:00 +0000 2010" 
}) 
items.find({ 
    created_at: { 
     $gte:"Mon May 30 18:47:00 +0000 2015", 
     $lt: "Sun May 30 20:40:36 +0000 2010" 
    } 
}) 
=> { "_id" : ObjectId("4c079123b9ec877893f33638"), "name" : "example", "created_at" : "Sun May 30 18.49:00 +0000 2010" } 

En el segundo ejemplo no se esperaban resultados, pero todavía había uno. Esto se debe a que se realiza una comparación básica de cadenas.

+2

Parece interesante, pero la fecha almacenada debe estar en un formato específico. Acabo de almacenar lo que me brindó Twitter. ¿Es necesario cambiar esto en un formato diferente? – Tom

+5

Probablemente haya almacenado las marcas de tiempo como cadenas, así que supongo que MongoDB no se dará cuenta de que en realidad son fechas. Por lo tanto, hacer una consulta de rango en ellos daría como resultado una consulta de rango alfabético (p."Jan Mon 01.01.2010" antes de "Jan Sun 01.01.1000"). Probablemente tenga sentido formatear todos los datos de fecha en el formato MongoDB, que creo que es simplemente la fecha de JavaScript. – ponzao

+2

Acabo de usar esto para convertir mis cadenas de objetos de fecha http://stackoverflow.com/questions/2900674/how-do-i-convert-a-property-in-mongodb-from-text-to-date-type – Tom

16

MongoDB realmente almacena los millis de una fecha como un int (64), según lo prescrito por http://bsonspec.org/#/specification

Sin embargo, puede ser bastante confuso cuando se recuperan las fechas como el controlador de cliente va a crear una instancia de un objeto de fecha con su propia zona horaria local El controlador de JavaScript en la consola mongo sin duda hará esto.

Por lo tanto, si se preocupa por sus zonas horarias, asegúrese de saber lo que se supone que debe ser cuando lo recupere. Esto no debería importar tanto para las consultas, ya que igual equivaldrá a la misma int (64), independientemente de la zona horaria en la que esté el objeto de su fecha (espero). Pero definitivamente haré consultas con objetos de fecha reales (no cadenas) y dejaré que el conductor haga su trabajo.

0

Traté en este modelo como por mis requisitos necesito para almacenar una fecha en la que cada vez se crea un objeto más adelante quiero recuperar todos los registros (documentos) entre dos fechas en mi archivo html yo estaba usando el siguiente formato dd/mm/aaaa

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 

<html> 
<head> 

    <script> 
//jquery 
    $(document).ready(function(){ 
    $("#select_date").click(function() { 
    $.ajax({ 
    type: "post", 
    url: "xxx", 
    datatype: "html", 
    data: $("#period").serialize(), 
    success: function(data){ 
    alert(data); 
    } ,//success 

    }); //event triggered 

    });//ajax 
    });//jquery 
    </script> 

    <title></title> 
</head> 

<body> 
    <form id="period" name='period'> 
     from <input id="selecteddate" name="selecteddate1" type="text"> to 
     <input id="select_date" type="button" value="selected"> 
    </form> 
</body> 
</html> 

en mi archivo py (pitón) i convertido en "fomate iso" en siguiente manera

date_str1 = request.POST["SelectedDate1"] 
SelectedDate1 = datetime.datetime.strptime(date_str1, '%m/%d/%Y').isoformat() 

y guardado en mi colección dbmongo con "SelectedDate" como el campo en mi colección

para recuperar los datos o documentos entre 2 fechas que solía siguiente consulta

db.collection.find("SelectedDate": {'$gte': SelectedDate1,'$lt': SelectedDate2}}) 
2

Convertir la fecha para la zona horaria GMT a medida que los está relleno en Mongo. De esa forma, nunca hay un problema de zona horaria. Luego haga los cálculos en el campo twitter/timezone cuando retire los datos para la presentación.

14

Para aclarar. Lo que es importante saber es que:

  • Sí, debe pasar un objeto Javascript Date.
  • Sí, tiene que ser ISODate amigable
  • Sí, desde mi experiencia conseguir que esto funcione, es necesario manipular la fecha de la norma ISO
  • Sí, la utilización de fechas es por lo general siempre es un proceso tedioso, y mongo es no es una excepción

aquí hay un fragmento de trabajo de código, donde hacemos un poco de manipulación de la fecha para asegurar Mongo (en este caso estoy usando módulo de mangosta y quiero resultados para las filas cuyo atributo de fecha es menor que (antes) del fecha dada como parámetro myDate) puede manejarlo correctamente:

var inputDate = new Date(myDate.toISOString()); 
MyModel.find({ 
    'date': { $lte: inputDate } 
}) 
+0

Muy útil. Ayudó mucho con un problema que tuve. Gracias –

2

¿Por qué no convertir la cadena a un número entero de la forma YYYYMMDDHHMMSS? Cada incremento de tiempo crearía un número entero más grande, y puede filtrar los enteros en lugar de preocuparse por la conversión a la hora ISO.

+0

Porque el tiempo no solo está sucediendo en mi zona horaria local. –

+1

Esto se convierte en una pesadilla una vez que empiezas a tener que convertir el tiempo hacia y desde ese formato en todas partes. Si va a hacer algo como esto, como mínimo use el valor de retorno de .getTime() desde un objeto de fecha JS. –

+1

por eso siempre almacenamos datos en UTC – codewandler

7
db.collection.find({"createdDate":{$gte:new ISODate("2017-04-14T23:59:59Z"),$lte:new ISODate("2017-04-15T23:59:59Z")}}).count(); 

Reemplazar collection con el nombre de la colección que desea ejecutar la consulta

0

Colección Nombre: órdenes

{ 
    "_id" : ObjectId("590070186bcc993d9c316ac1"), 
    "updatedAt" : ISODate("2017-04-26T10:07:04.344Z"), 
    "createdAt" : ISODate("2017-04-26T10:02:00.489Z"), 
    "fullName" : "test last", 
    "imgLength" : 5, 
    "firstName" : "test", 
    "lastName" : "last", 
    "address" : "test", 
    "state" : "test", 
    "city" : "test", 
    "zipCode" : 123456, 
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"), 
    "orderId" : "PHA454494125243881", 
    "status" : "Pending", 
    "imgUrls" : [ ], 
    "__v" : 0 
} 
{ 
    "_id" : ObjectId("590071622e6d953e411dec3f"), 
    "updatedAt" : ISODate("2017-04-20T10:37:46.569Z"), 
    "createdAt" : ISODate("2017-04-20T10:07:30.572Z"), 
    "fullName" : "test last", 
    "imgLength" : 5, 
    "firstName" : "test", 
    "lastName" : "last", 
    "address" : "test", 
    "state" : "test", 
    "city" : "test", 
    "zipCode" : 123456, 
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"), 
    "orderId" : "PHA300991061399836", 
    "status" : "Pending", 
    "imgUrls" : [ ], 
    "__v" : 0 
} 
{ 
    "_id" : ObjectId("590071902e6d953e411dec40"), 
    "updatedAt" : ISODate("2017-04-15T10:08:16.111Z"), 
    "createdAt" : ISODate("2017-04-15T10:08:16.111Z"), 
    "fullName" : "test last", 
    "imgLength" : 5, 
    "firstName" : "test", 
    "lastName" : "last", 
    "address" : "test", 
    "state" : "test", 
    "city" : "test", 
    "zipCode" : 123456, 
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"), 
    "orderId" : "PHA876174070036339", 
    "status" : "Pending", 
    "imgUrls" : [ ], 
    "__v" : 0 
} 

Si desea obtener los datos entre dos fechas, entonces se puede correr por debajo de consulta:

db.orders.find({ 
      createdAt:{ 
        $gt:ISODate("2017-04-10T10:08:16.111Z"), 
        $lt:ISODate("2017-05-25T10:08:16.111Z")} 
       }).pretty(); 

el resultado sería:

[ 

    { 
     "_id" : ObjectId("590071622e6d953e411dec3f"), 
     "updatedAt" : ISODate("2017-04-20T10:37:46.569Z"), 
     "createdAt" : ISODate("2017-04-20T10:07:30.572Z"), 
     "fullName" : "test last", 
     "imgLength" : 5, 
     "firstName" : "test", 
     "lastName" : "last", 
     "address" : "test", 
     "state" : "test", 
     "city" : "test", 
     "zipCode" : 123456, 
     "user" : ObjectId("58f760e771fd1737d1f9b4e5"), 
     "orderId" : "PHA300991061399836", 
     "status" : "Pending", 
     "imgUrls" : [ ], 
     "__v" : 0 
    } 
    { 
     "_id" : ObjectId("590071902e6d953e411dec40"), 
     "updatedAt" : ISODate("2017-04-15T10:08:16.111Z"), 
     "createdAt" : ISODate("2017-04-15T10:08:16.111Z"), 
     "fullName" : "test last", 
     "imgLength" : 5, 
     "firstName" : "test", 
     "lastName" : "last", 
     "address" : "test", 
     "state" : "test", 
     "city" : "test", 
     "zipCode" : 123456, 
     "user" : ObjectId("58f760e771fd1737d1f9b4e5"), 
     "orderId" : "PHA876174070036339", 
     "status" : "Pending", 
     "imgUrls" : [ ], 
     "__v" : 0 
    } 
] 
1

uso $ obtener y $ lt encontrar entre de datos de fecha en mongodb

var tomorrowDate = moment(new Date()).add(1, 'days').format("YYYY-MM-DD"); 
db.collection.find({"plannedDeliveryDate":{ $gte: new Date(tomorrowDate +"T00:00:00.000Z"),$lt: new Date(tomorrowDate + "T23:59:59.999Z")}}) 
2

Python y pymongo

Encontrar objetos entre dos fechas en Python con pymongo en colección posts (basado en el tutorial):

from_date = datetime.datetime(2010, 12, 31, 12, 30, 30, 125000) 
to_date = datetime.datetime(2011, 12, 31, 12, 30, 30, 125000) 

for post in posts.find({"date": {"$gte": from_date, "$lt": to_date}}): 
    print(post) 

Dónde {"$gte": from_date, "$lt": to_date} especifica el rango en términos de datetime.datetime tipos.

Cuestiones relacionadas