MongoDB / pertanyaan luwak pada tanggal tertentu?

141

Apakah mungkin untuk meminta tanggal tertentu?

Saya menemukan di Cookbook mongo bahwa kita dapat melakukannya untuk rentang Permintaan untuk Rentang Tanggal Seperti itu:

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

Tetapi apakah mungkin untuk tanggal tertentu? Ini tidak berfungsi:

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

Jawaban:

211

Itu akan berfungsi jika tanggal yang Anda simpan di DB tanpa waktu (hanya tahun, bulan, hari).

Kemungkinannya adalah tanggal yang Anda simpan adalah new Date(), yang mencakup komponen waktu. Untuk menanyakan waktu-waktu itu, Anda perlu membuat rentang tanggal yang mencakup semua momen dalam sehari.

db.posts.find( //query today up to tonight
  {"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})
Roy
sumber
29
Ingatlah bahwa dalam fungsi Date (), argumen bulan mulai menghitung pada 0, bukan 1. Di sisi lain, hari-hari mulai menghitung pada 1 ... detail
Mark Stosberg
bukankah lebih baik melakukan _ 1 hari untuk mendapatkan kencan berikutnya daripada hard code keduanya?
raju
2
Apakah metode ini berfungsi dengan baik jika tanggal disimpan seperti ini: >> "date": ISODate ("2016-01-04T14: 07: 17.496Z")
santhosh
Apakah Anda tidak memiliki bulan dan tanggal Anda beralih. Format tanggal harus: yyyy, dd, MM
thethakuri
123

... 5+ tahun kemudian, saya sangat menyarankan menggunakan date-fns sebagai gantinya

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

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

Bagi kita yang menggunakan Moment.js

const moment = require('moment')

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

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

Penting: semua momen bisa berubah !

tomorrow = today.add(1, 'days')tidak berfungsi karena ia juga bermutasi today. Memanggil moment(today)memecahkan masalah itu dengan kloning secara implisit today.

Dermaga-Luc Gendreau
sumber
13
Saya menyarankan untuk menggunakan .startOf('day').hours (0) .minutes (0) .seconds (0). Jadi baris pertama adalah:var today = moment().startOf('day')
Jim Geurts
2
Jika kita menggunakan moment(today)untuk mengkloning objek, solusi lain adalah:var tomorrow = today.clone().add(1, 'days')
johntellsall
1
@johntellsall Kloning eksplisit daripada implisit, hasil yang sama tetapi mungkin memang lebih mudah dibaca!
Pier-Luc Gendreau
1
Atau, saya bisa menyarankan berikut untuk $lt: moment(today).endOf('day'). Untuk mencegah hasil aktual dari hari berikutnya dimasukkan.
greduan
1
bagi saya moment(today).endOf('day')memberikan hari yang sama dengan waktu: 23:59:59.999. Jadi sebenarnya terlihat lebih tepat untuk digunakan $lte, jika tidak objek pada waktu tertentu akan diabaikan.
leonprou
11

Ya, objek Date sesuai dengan tanggal dan waktu, jadi membandingkannya dengan nilai date saja tidak berfungsi.

Anda cukup menggunakan operator $ where untuk mengekspresikan kondisi yang lebih rumit dengan ekspresi boolean Javascript :)

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

created_onadalah bidang datetime dan 2012-07-14merupakan tanggal yang ditentukan.

Tanggal harus persis dalam format YYYY-MM-DD .

Catatan: Gunakan $wherehemat, ini memiliki implikasi kinerja.

Faisal Hasnain
sumber
10

Sudahkah Anda mencoba:

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

Masalah yang akan Anda hadapi adalah bahwa tanggal disimpan sebagai cap waktu dalam bahasa Mongo. Jadi, untuk mencocokkan tanggal Anda memintanya untuk mencocokkan cap waktu. Dalam kasus Anda, saya pikir Anda mencoba mencocokkan satu hari (mis. Mulai pukul 00:00 hingga 23:59 pada tanggal tertentu). Jika kencan Anda disimpan tanpa waktu maka Anda harus baik-baik saja. Jika tidak, coba tentukan tanggal Anda sebagai rentang waktu pada hari yang sama (mis. Mulai = 00: 00, akhir = 23: 59) jika gte tidak berfungsi.

pertanyaan serupa

Michael D Johnson
sumber
1
Ini akan mencakup semua elemen yang lebih muda dari tanggal yang ditentukan, yang mungkin bukan yang diinginkan OP. Pertimbangkan untuk menambahkan opsi "lt" seperti jawaban lainnya.
BenSower
Saya pikir jika Anda memiliki $gtebukannya gteakan lebih baik.
dongkrak
Ini sudah dijawab dengan lebih benar di atas, tetapi itu menggangguku mengetahui bahwa jawaban saya tidak aktif, jadi saya memperbaruinya agar benar untuk pertanyaan itu. Hei, sudah 4 tahun. lol
Michael D Johnson
6

Anda dapat menggunakan pendekatan berikut untuk metode API untuk mendapatkan hasil dari hari tertentu:

# [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'
Daniel Kmak
sumber
1

Kami memiliki masalah yang berkaitan dengan data duplikat dalam database kami, dengan bidang tanggal memiliki beberapa nilai di mana kami seharusnya memiliki 1. Saya pikir saya akan menambahkan cara kami menyelesaikan masalah untuk referensi.

Kami memiliki koleksi yang disebut "data" dengan bidang "nilai" numerik dan bidang "tanggal". Kami memiliki proses yang kami pikir idempoten, tetapi akhirnya menambahkan 2 x nilai per hari pada putaran kedua:

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

Kami hanya perlu 1 dari 2 catatan, jadi harus menggunakan javascript untuk membersihkan db. Pendekatan awal kami akan beralih melalui hasil dan menghapus bidang apa pun dengan waktu antara 06:00 dan 11:00 (semua duplikat di pagi hari), tetapi selama implementasi, membuat perubahan. Berikut skrip yang digunakan untuk memperbaikinya:

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

dan kemudian menjalankannya mongo thedatabase fixer_script.js

Brett
sumber