La requête de date avec ISODate dans mongodb ne semble pas fonctionner

189

Je ne semble pas être en mesure de faire fonctionner même la requête de date la plus élémentaire dans MongoDB. Avec un document qui ressemble à ceci:

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

Et une requête qui ressemble à ceci:

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

J'obtiens 0 résultat en exécutant:

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

Une idée pourquoi cela ne fonctionne pas?

Pour référence, cette requête est produite par MongoTemplate de Spring, donc je n'ai pas de contrôle direct sur la requête qui est finalement envoyée à MongoDB.

(PS)

> db.version()
2.4.7

Merci!

Jason Polites
la source

Réponses:

312

Bien $dateque cela fasse partie de MongoDB Extended JSON et que ce soit ce que vous obtenez par défaut avec, mongoexportje ne pense pas que vous puissiez vraiment l'utiliser dans le cadre de la requête.

Si vous essayez une recherche exacte avec $datecomme ci-dessous:

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

vous obtiendrez une erreur:

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

Essaye ça:

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

ou (suite aux commentaires de @ user3805045 ):

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

ISODatepeut également être nécessaire de comparer les dates sans heure (noté par @MattMolnar ).

Selon les types de données dans mongo Shell, les deux devraient être équivalents:

Le shell mongo fournit diverses méthodes pour renvoyer la date, sous forme de chaîne ou d'objet Date:

  • Date () méthode qui renvoie la date actuelle sous forme de chaîne.
  • nouveau constructeur Date () qui renvoie un objet Date à l'aide de l'encapsuleur ISODate ().
  • Constructeur ISODate () qui renvoie un objet Date à l'aide du wrapper ISODate ().

et l'utilisation ISODate doit toujours renvoyer un objet Date .

{"$date": "ISO-8601 string"}peut être utilisé lorsqu'une représentation JSON stricte est requise. Un exemple possible est le connecteur Hadoop.

zéro323
la source
3
Ouais. Je pense que j'ai été bouleversé par ce qui est retourné lorsque vous imprimez l' Queryobjet au printemps. La forme sérialisée de la requête n'est pas nécessairement une requête valide que vous pouvez simplement copier / coller dans un shell mongo, ce qui en soi est assez frustrant. Le coupable est ici: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
Jason Polites
2
Lors de la comparaison d'une date partielle (sans heure), j'ai dû passer de new Date('2016-03-09')à ISODate('2016-03-09'). Le premier renverrait des dates dans le passé pour une $gterequête.
Matt Molnar
@MattMolnar Noted, et a mis à jour la réponse avec une attribution. Merci.
zero323
92

À partir des commentaires de la page du livre de recettes MongoDB :

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

Cela a fonctionné pour moi. Dans le contexte complet, la commande suivante récupère tous les enregistrements où le dtchamp de date a une date sur 2013-10-01 (AAAA-MM-JJ) Zulu:

db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})
Steve HHH
la source
1
J'ai eu une erreur "ISODate undefined". Je n'ai pas pu résoudre ce problème.
Batuhan Akkaya
@BatuhanAkkaya En python avec pymongo, datetime.datetimeéquivaut à ISODate.
jtbr
12

Essaye ça:

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

J'utilise robomongo comme interface graphique client mongodb et ce qui suit a fonctionné pour moi

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

Du côté de l'application, j'utilise le pilote basé sur nodejs mongodb (v1.4.3), l'application utilise datepicker dans l'interface utilisateur qui donne la date comme YYYY-mm-dd, ceci est ensuite ajouté avec l'heure par défaut comme 00:00:00 puis donné au new Date()constructeur et ensuite fourni à l'objet de critères mongodb, je pense que le pilote convertit la date en date ISO et la requête fonctionne alors et donne la sortie souhaitée, mais le même new Date()constructeur ne fonctionne pas ou n'affiche pas la même sortie sur robo mongo, pour le même critères, ce qui est bizarre, car j'ai utilisé robomongo pour recouper mes objets critères.

Alors que le cli mongoshell par défaut fonctionne bien avec ISODateetnew Date()

siddharthrc
la source
1
Merci pour la pointe, Robomongo est bien meilleur que Mongo Compass
Alex
5

En mode strict json, vous devrez garder l'ordre:

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

Seule chose qui a fonctionné pour définir mes requêtes de recherche sur mlab.com.

3vangelos
la source
Erreur lors de l'exécution de la requête. Raison: (invalid_operator) Opérateur invalide: $ date
sabre tabatabaee yazdi
2

Dans le shell MongoDB:

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

Dans mon code nodeJS (en utilisant Mongoose)

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

J'interroge ma collection d'événements de capteur pour renvoyer des valeurs où le champ «de» est supérieur à la date donnée

Lewma
la source
4
Bienvenue dans Stack Overflow! Veuillez simplement poster la réponse à la question, et non des éléments supplémentaires comme "Ceci est mon premier message". Considérez Stack Overflow comme Wikipédia, pas comme un forum.
durron597
1

c'est mon document

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

maintenant je veux trouver tous les 27 documents de date, donc j'ai utilisé ceci ...

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

result:1

cela a fonctionné pour moi.

codeur
la source
0

Cela a fonctionné pour moi en recherchant une valeur inférieure ou égale à maintenant:

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

Enveloppez-le avec new Date():

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

Ancienne question, mais toujours le premier hit google, alors je la poste ici pour la retrouver plus facilement ...

En utilisant Mongo 4.2 et un agrégat ():

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

Celui-ci vous donne la variable groupby en tant que date, parfois mieux à utiliser comme composants eux-mêmes.

A. Rabus
la source