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.