Zapytania MongoDB / Mongoose w określonym dniu?


Odpowiedzi:


212

To powinno działać, jeśli daty zapisane w bazie danych są bez czasu (tylko rok, miesiąc, dzień).

Możliwe, że zapisałeś daty new Date(), które obejmują składniki czasu. Aby sprawdzić te czasy, musisz utworzyć zakres dat obejmujący wszystkie momenty w ciągu dnia.

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

29
Pamiętaj, że w funkcji Date () argument miesiąc zaczyna liczyć od 0, a nie od 1. Z drugiej strony, dni liczone są od 1 ... szczegóły
Mark Stosberg

czy nie lepiej jest zrobić _ 1 dzień, aby uzyskać następną datę, zamiast na stałe zakodować oba z nich?
raju

2
Czy ta metoda działa dobrze, jeśli data jest przechowywana w następujący sposób: >> "date": ISODate ("2016-01-04T14: 07: 17.496Z")
santhosh

Nie masz swoich miesięcy i zmian daty. Format dat powinien być następujący: yyyy, dd, MM
thethakuri

123

... 5+ lat później zdecydowanie sugeruję użycie zamiast tego date-fns

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

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

Dla tych z nas, którzy używają Moment.js.

const moment = require('moment')

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

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

Ważne: wszystkie momenty są zmienne !

tomorrow = today.add(1, 'days')nie działa, ponieważ również mutuje today. Wywołanie moment(today)rozwiązuje ten problem przez niejawne klonowanie today.


13
Sugeruję użycie .startOf('day')zamiast .hours (0) .minutes (0) .seconds (0). Tak więc pierwsza linia var today = moment().startOf('day')
brzmiałaby

2
Jeśli używamy moment(today)do klonowania obiektu, innym rozwiązaniem jest:var tomorrow = today.clone().add(1, 'days')
johntellsall

1
@johntellsall Klonowanie jawne zamiast niejawnego, ten sam wynik, ale być może rzeczywiście łatwiejszy do odczytania!
Pier-Luc Gendreau

1
Ewentualnie mogę zaproponować następujące zalecenia $lt: moment(today).endOf('day'). Aby zapobiec uwzględnieniu rzeczywistych wyników z następnego dnia.
greduan

1
mi moment(today).endOf('day')daje ten sam dzień z czasów: 23:59:59.999. W rzeczywistości wygląda to bardziej poprawnie w użyciu $lte, w przeciwnym razie obiekty w tym konkretnym czasie zostaną zignorowane.
leonprou,

11

Tak, obiekt Date uzupełnia datę i godzinę, więc porównywanie go tylko z wartością daty nie działa.

Możesz po prostu użyć operatora $ where , aby wyrazić bardziej złożony warunek za pomocą wyrażenia logicznego JavaScript :)

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

created_onjest polem 2012-07-14daty i godziny i jest określoną datą.

Data powinna być dokładnie w formacie RRRR-MM-DD .

Uwaga: używaj $whereoszczędnie, ma to wpływ na wydajność.


10

Czy próbowałeś:

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

Problem, z którym się spotkasz, polega na tym, że daty są przechowywane jako znaczniki czasu w Mongo. Tak więc, aby dopasować datę, chcesz, aby pasowała do znacznika czasu. W twoim przypadku myślę, że próbujesz dopasować dzień (tj. Od 00:00 do 23:59 w określonym dniu). Jeśli twoje daty są przechowywane bez czasu, powinieneś być w porządku. W przeciwnym razie spróbuj określić datę jako zakres czasu tego samego dnia (np. Start = 00: 00, koniec = 23: 59), jeśli gte nie działa.

podobne pytanie


1
Obejmuje to wszystkie elementy młodsze niż określona data, co prawdopodobnie nie jest tym, czego chciał OP. Rozważ dodanie opcji „lt”, takiej jak inne odpowiedzi.
BenSower

Myślę, że gdybyś miał $gtezamiast tego gte, byłoby lepiej.
gniazdo jack puste

Na to odpowiedź została już poprawiona powyżej, ale przeszkadzała mi świadomość, że moja odpowiedź jest wyłączona, więc zaktualizowałem ją, aby była poprawna dla pytania. Hej, to już 4 lata. lol
Michael D Johnson

6

Możesz zastosować następujące podejście do metody API, aby uzyskać wyniki z określonego dnia:

# [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'

1

Mieliśmy problem ze zduplikowanymi danymi w naszej bazie danych, z polem daty zawierającym wiele wartości, w których mieliśmy mieć 1. Pomyślałem, że dodam sposób, w jaki rozwiązaliśmy ten problem w celach informacyjnych.

Mamy zbiór o nazwie „dane” z polem numerycznym „wartość” i polem „data”. Mieliśmy proces, który uważaliśmy za idempotentny, ale ostatecznie dodaliśmy 2 x wartości dziennie przy drugim uruchomieniu:

{ "_id" : "1", "type":"x", "value":1.23, date : ISODate("2013-05-21T08:00:00Z")}
{ "_id" : "2", "type":"x", "value":1.23, date : ISODate("2013-05-21T17:00:00Z")}

Potrzebujemy tylko 1 z 2 rekordów, więc musieliśmy skorzystać z javascript, aby wyczyścić bazę danych. Nasze początkowe podejście polegało na iteracji wyników i usunięciu dowolnego pola z czasem między 6 rano a 11 rano (wszystkie duplikaty były rano), ale podczas wdrażania wprowadzono zmianę. Oto skrypt użyty do rozwiązania tego problemu:

var data = db.data.find({"type" : "x"})
var found = [];
while (data.hasNext()){
    var datum = data.next();
    var rdate = datum.date;
    // instead of the next set of conditions, we could have just used rdate.getHour() and checked if it was in the morning, but this approach was slightly better...
    if (typeof found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] !== "undefined") {
       if (datum.value != found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()]) {
           print("DISCREPENCY!!!: " + datum._id + " for date " + datum.date);
       }
       else {
           print("Removing " + datum._id);
           db.data.remove({ "_id": datum._id});
       }
    }
    else {
       found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] = datum.value;
    }
}

a następnie uruchomiłem go z mongo thedatabase fixer_script.js

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.