2010-05-31 5 views
252

Je joue le stockage autour de tweets à l'intérieur MongoDB, chaque objet ressemble à ceci:Trouver des objets entre deux dates 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 
} 

Comment pourrais-je écrire une requête qui vérifie la created_at et trouve tous les objets entre 18h47 et 19h00? Ai-je besoin de mettre à jour mes documents pour que les dates soient stockées dans un format spécifique?

+0

Vous ne dites pas quel champ vous voulez interroger? – shingara

+0

Oups, je veux interroger le created_at et trouver tout entre deux dates. – Tom

+0

Je suis curieux de savoir pourquoi ne pas utiliser l'horodatage, des avantages en utilisant la date Obj? – Leo

Répondre

395

Querying for a Date Range (Specific Month or Day) dans le MongoDB Cookbook a une très bonne explication sur la question, mais au-dessous est quelque chose que j'ai essayé moi-même et il semble fonctionner.

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

Sur la base de mes expériences, vous aurez besoin de sérialisation vos dates dans un format qui prend en charge MongoDB, parce que les éléments suivants ont donné des résultats de recherche indésirables.

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

Dans le deuxième exemple, aucun résultat n'était attendu, mais il en restait un. C'est parce qu'une comparaison de chaîne de base est faite.

+2

Cela semble intéressant, mais la date stockée doit être dans un format spécifique. Je viens de stocker ce qui a été fourni par Twitter, est-ce que cela doit être changé dans un format différent? – Tom

+5

Vous avez probablement stocké les horodateurs comme des chaînes, donc je devine que MongoDB ne réalisera pas qu'ils sont en fait des dates. Ainsi, en faisant une requête de plage sur celles-ci, on obtiendrait une requête de plage alphabétique (par ex."Jan lun 01.01.2010" étant avant "Jan Sun 01.01.1000"). Il serait probablement judicieux de formater toutes les données de date dans le format MongoDB, ce qui, je pense, est tout simplement JavaScript Date. – ponzao

+2

Je viens de l'utiliser pour convertir mes chaînes en objets de date http://stackoverflow.com/questions/2900674/how-do-i-convert-a-property-in-mongodb-from-text-to-date-type – Tom

16

MongoDB stocke en fait les Millis d'une date comme int (64), tel que prescrit par http://bsonspec.org/#/specification

Cependant, il peut être assez déroutant lorsque vous récupérez les dates que le pilote client instancier un objet rendez-vous avec sa propre fuseau horaire local. Le pilote JavaScript de la console mongo le fera certainement. Donc, si vous vous souciez de vos fuseaux horaires, alors assurez-vous de savoir ce que c'est censé être quand vous le récupérez. Cela ne devrait pas avoir autant d'importance pour les requêtes, car cela équivaudra toujours au même int (64), quel que soit le fuseau horaire dans lequel se trouve votre objet date (j'espère). Mais je ferais certainement des requêtes avec des objets de date réels (pas de chaînes) et laisserais le conducteur faire son truc.

0

j'ai essayé dans ce modèle selon mes besoins je dois stocker une date à laquelle jamais un objet est créé, je veux plus tard pour récupérer tous les dossiers (documents) entre deux dates dans mon fichier html j'utilisais ce qui suit fichier format mm/jj/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> 

dans mon py (python) i il converti en "iso fomate" en suivant façon

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

et enregistré dans ma collection de dbmongo avec "SelectedDate" comme champ dans ma collection

pour récupérer des données ou des documents entre 2 dates i utilisé après requête

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

Convertissez vos dates pour fuseau horaire GMT que vous les farcir dans Mongo. De cette façon, il n'y a jamais de problème de fuseau horaire. Ensuite, faites le calcul sur le champ twitter/timezone lorsque vous récupérez les données pour la présentation.

14

Pour clarifier. Ce qu'il est important de savoir, c'est que:

  • Oui, vous devez transmettre un objet Date Javascript.
  • Oui, il doit être ISODate amical
  • Oui, de mon expérience obtenir que cela fonctionne, vous devez manipuler la date ISO
  • Oui, travailler avec des dates est généralement toujours un processus fastidieux, et mongo est pas exception

Voici un extrait de travail de code, où nous faisons un peu de manipulation de jour pour assurer Mongo (ici je suis en utilisant le module mangouste et que vous souhaitez des résultats pour les lignes dont l'attribut la date est inférieure à (avant) le date donnée comme myDate param) peut gérer correctement:

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

Très utile. A beaucoup aidé avec un problème que j'avais. Merci –

2

Pourquoi ne pas convertir la chaîne en un entier de la forme YYYYMMDDHHMMSS? Chaque incrément de temps crée alors un entier plus grand, et vous pouvez filtrer sur les entiers au lieu de vous soucier de la conversion en heure ISO.

+0

Parce que le temps ne se passe pas seulement dans mon fuseau horaire local. –

+1

Cela devient un cauchemar une fois que vous commencez à convertir l'heure de et vers ce format partout. Si vous voulez faire quelque chose comme ça, utilisez au minimum la valeur de retour de .getTime() à partir d'un objet date JS. –

+1

thats pourquoi nous stockons toujours des données dans UTC – codewandler

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

Remplacer collection avec le nom de collection que vous voulez exécuter la requête

0

Nom de la collection: commandes

{ 
    "_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 vous souhaitez obtenir les données entre deux dates, vous pouvez exécuter la requête ci-dessous:

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

votre résultat serait:

[ 

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

utilisation $ se et $ lt trouver entre de données date dans 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 et pymongo

objets Trouver entre deux dates en Python avec pymongo dans collection posts (sur la base 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) 

{"$gte": from_date, "$lt": to_date} spécifie la gamme en termes de types datetime.datetime.

Questions connexes