174 votes

MongoDB/Mongoose effectuant des requêtes à une date précise ?

Est-il possible d'interroger une date spécifique ?

J'ai trouvé dans le Cookbook de Mongo que nous pouvons le faire pour une gamme Recherche d'une plage de dates Comme ça :

db.posts.find({"created_on": {"$gte": start, "$lt": end}})

Mais est-ce possible pour une date précise ? Cela ne fonctionne pas :

db.posts.find({"created_on": new Date(2012, 7, 14) })

264voto

rdrey Points 3328

Cela devrait fonctionner si les dates que vous avez enregistrées dans la base de données ne comportent pas d'heure (seulement l'année, le mois et le jour).

Il est probable que les dates que vous avez sauvegardées étaient new Date() qui comprend les composantes temporelles. Pour interroger ces heures, vous devez créer une plage de dates qui inclut tous les moments d'une journée.

db.posts.find({ //query today up to tonight
    created_on: {
        $gte: new Date(2012, 7, 14), 
        $lt: new Date(2012, 7, 15)
    }
})

44 votes

Rappelez-vous que dans la fonction Date(), l'argument du mois commence à compter à 0, et non à 1. Par contre, les jours commencent à compter à 1... détails

0 votes

N'est-il pas préférable de faire _ 1 jour pour obtenir la date suivante plutôt que de coder en dur les deux ?

2 votes

Cette méthode fonctionne bien si la date est stockée comme ceci:>> "date" : ISODate("2016-01-04T14:07:17.496Z")

170voto

Pier-Luc Gendreau Points 2288

...5+ ans plus tard, je suggère fortement d'utiliser date-fns au lieu de

import endOfDayfrom 'date-fns/endOfDay'
import startOfDay from 'date-fns/startOfDay'

MyModel.find({
  createdAt: {
    $gte: startOfDay(new Date()),
    $lte: endOfDay(new Date())
  }
})

Pour ceux d'entre nous qui utilisent Moment.js

const moment = require('moment')

const today = moment().startOf('day')

MyModel.find({
  createdAt: {
    $gte: today.toDate(),
    $lte: moment(today).endOf('day').toDate()
  }
})

Important : tous les moments sont mutables ¡!

tomorrow = today.add(1, 'days') ne fonctionne pas puisqu'elle fait aussi muter today . Appeler moment(today) résout ce problème en clonant implicitement today .

15 votes

Je suggère d'utiliser .startOf('day') au lieu de .hours(0).minutes(0).seconds(0). Ainsi, la première ligne serait : var today = moment().startOf('day')

2 votes

Si nous utilisons moment(today) pour cloner l'objet, une autre solution est : var tomorrow = today.clone().add(1, 'days')

1 votes

@johntellsall Clonage explicite plutôt qu'implicite, même résultat mais peut-être plus facile à lire en effet !

13voto

Faisal Hasnain Points 9

Oui, l'objet Date comprend la date et l'heure, donc le comparer avec une simple valeur de date ne fonctionne pas.

Vous pouvez simplement utiliser le pour exprimer une condition plus complexe avec une expression booléenne en Javascript :)

db.posts.find({ '$where': 'this.created_on.toJSON().slice(0, 10) == "2012-07-14"' })

created_on est le champ datetime et 2012-07-14 est la date spécifiée.

La date doit être exactement en AAAA-MM-JJ format.

Note : Utilisez $where avec parcimonie, cela a des conséquences sur les performances.

0 votes

J'ai utilisé votre réponse qui donne l'erreur Où n'est pas autorisé dans ce niveau de l'atlas comment le résoudre ?

10voto

Michael D Johnson Points 421

Avez-vous essayé :

db.posts.find({"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})

Le problème que vous allez rencontrer est que les dates sont stockées sous forme d'horodatage dans Mongo. Donc, pour faire correspondre une date, vous lui demandez de faire correspondre un horodatage. Dans votre cas, je pense que vous essayez de faire correspondre un jour (c'est-à-dire de 00:00 à 23:59 à une date spécifique). Si vos dates sont stockées sans les heures, tout devrait bien se passer. Sinon, essayez de spécifier votre date en tant qu'intervalle de temps le même jour (par exemple, start=00:00, end=23:59) si gte ne fonctionne pas.

question similaire

1 votes

Cela inclura tous les éléments plus jeunes que la date spécifiée, ce qui n'est probablement pas ce que le PO voulait. Envisagez d'ajouter une option "lt" comme les autres réponses.

0 votes

Je pense que si vous avez $gte au lieu de gte ce serait mieux.

0 votes

Cette question a déjà été répondue plus correctement ci-dessus, mais cela me dérangeait de savoir que ma réponse était fausse, alors je l'ai mise à jour pour qu'elle soit correcte pour la question. Hé, ça fait 4 ans. lol

6voto

Daniel Points 1386

Vous pouvez utiliser l'approche suivante pour la méthode API afin d'obtenir les résultats d'un jour spécifique :

# [HTTP GET]
getMeals: (req, res) ->
  options = {}
  # eg. api/v1/meals?date=Tue+Jan+13+2015+00%3A00%3A00+GMT%2B0100+(CET)
  if req.query.date?
    date = new Date req.query.date
    date.setHours 0, 0, 0, 0
    endDate = new Date date
    endDate.setHours 23, 59, 59, 59
    options.date =
      $lt: endDate
      $gte: date

  Meal.find options, (err, meals) ->
      if err or not meals
        handleError err, meals, res
      else
        res.json createJSON meals, null, 'meals'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X