MongoDB / Belirli bir tarihte Mongoose sorgulaması?


141

Belirli bir tarihi sorgulamak mümkün müdür?

Bence bir aralığı için bunu yapabileceği Mongo Cookbook'ta bulunan bir tarihi Aralığı için Sorgulama gibi olun:

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

Ancak belirli bir tarih için mümkün mü? Bu işe yaramaz:

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

Yanıtlar:


213

DB'ye kaydettiğiniz tarihler zamana sahip değilse (sadece yıl, ay, gün) bu işe yarar.

Büyük olasılıkla new Date(), zaman bileşenlerini içeren kaydettiğiniz tarihler olabilir . Bu saatleri sorgulamak için bir günün tüm anlarını içeren bir tarih aralığı oluşturmanız gerekir.

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

29
Date () işlevinde ay bağımsız değişkeninin 1 değil 0'da başladığını unutmayın. Öte yandan, günler 1'de saymaya başlar ... ayrıntılar
Mark Stosberg

her ikisi de sabit kod yerine sonraki tarih almak için _ 1 gün yapmak daha iyi değil mi?
raju

2
Tarih şu şekilde saklanırsa bu yöntem iyi çalışır mı: >> "tarih": ISODate ("2016-01-04T14: 07: 17.496Z")
santhosh

Aylar ve tarih anahtarlarınız yok mu? Tarih formatı şöyle olmalıdır: yyyy, dd, MM
thethakuri

124

... 5+ yıl sonra bunun yerine date-fns kullanmanızı şiddetle tavsiye ederim

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

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

Moment.js kullananlarımız için

const moment = require('moment')

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

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

Önemli: tüm anlar değiştirilebilir !

tomorrow = today.add(1, 'days')aynı zamanda mutasyona uğradığı için çalışmaz today. Arayan moment(today)örtük klonlama yoluyla çözen bu sorunu today.


14
.startOf('day').Hours (0) .minutes (0) .seconds (0) yerine kullanmanızı öneririm . İlk satır şöyle olur:var today = moment().startOf('day')
Jim Geurts

2
moment(today)Nesneyi klonlamak için kullanırsak , başka bir çözüm:var tomorrow = today.clone().add(1, 'days')
johntellsall

1
@johntellsall Örtük, aynı sonuç yerine açık klonlama, ama belki de daha kolay okunması!
Pier-Luc Gendreau

1
Alternatif olarak, ben için aşağıdakileri hatırlatıyoruz $lt: moment(today).endOf('day'). Ertesi günün gerçek sonuçlarının dahil edilmesini önlemek için.
greduan

1
Benim için moment(today).endOf('day')zamanında aynı gün verir: 23:59:59.999. Bu yüzden aslında kullanımı daha doğru görünüyor $lte, aksi takdirde belirli bir zamandaki nesneler yok sayılır.
leonprou

11

Evet, Date nesnesi tarih ve saati birleştirir, bu nedenle bunu yalnızca tarih değeriyle karşılaştırmak işe yaramaz.

Javascript boole ifadesiyle daha karmaşık bir durumu ifade etmek için $ where operatörünü kullanabilirsiniz :)

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

created_ondatetime alanıdır ve 2012-07-14belirtilen tarihtir.

Tarih tam olarak YYYY-AA-GG biçiminde olmalıdır.

Not:$where Tutumlu kullanın , performans sonuçları vardır.


10

Denedin mi:

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

Karşılaşacağınız sorun, tarihlerin Mongo'da zaman damgaları olarak depolanmasıdır. Yani, bir tarihle eşleştirmek için sizden bir zaman damgasıyla eşleşmesini istersiniz. Sizin durumunuzda bir günü eşleştirmeye çalıştığınızı düşünüyorum (yani belirli bir tarihte 00:00 - 23:59). Tarihleriniz zaman olmadan saklanırsa, iyi olmalısınız. Aksi takdirde, gte işe yaramazsa, tarihinizi aynı gün içinde bir zaman aralığı olarak belirtmeyi deneyin (örn. Başlangıç ​​= 00: 00, bitiş = 23: 59).

benzer soru


1
Bu, belirtilen tarihten daha genç olan tüm öğeleri içerecektir, bu muhtemelen OP'nin istediği şey değildir. Diğer cevaplar gibi bir "lt" seçeneği eklemeyi düşünün.
BenSower

Bence sen onun $gteyerine gtedaha iyi olurdu.
jack blank

Bu daha önce yukarıda daha doğru bir şekilde cevaplandı, ancak cevabımın kapalı olduğunu bilerek beni rahatsız ediyordu, bu yüzden soru için doğru olacak şekilde güncelledim. Hey, 4 yıl oldu. lol
Michael D Johnson

6

Belirli bir günden sonuçları almak için API yöntemi için aşağıdaki yaklaşımı kullanabilirsiniz:

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

Veritabanımızda yinelenen verilerle ilgili bir sorun yaşadık, tarih alanı 1 olması gereken birden fazla değere sahipti. Sorunu referans için çözdüğümüz yolu ekleyeceğimi düşündüm.

Sayısal "değer" alanı ve tarih "tarih" alanı içeren "veri" adlı bir koleksiyonumuz var. İdempotent olduğunu düşündüğümüz bir süreç vardı, ancak ikinci çalışmada günde 2 x değer ekledik:

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

Biz sadece 2 kayıtları 1 gerekir, bu yüzden db temizlemek için javascript başvurmak zorunda kaldı. İlk yaklaşımımız, sonuçları yinelemek ve 06: 00-11: 00 saatleri arasında (tüm kopyalar sabah idi) herhangi bir alanı kaldırmak olacaktı, ancak uygulama sırasında bir değişiklik yaptı. Düzeltmek için kullanılan komut dosyası şöyledir:

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

ve sonra ile koştu mongo thedatabase fixer_script.js

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.