MongoDB / Mongoose สอบถามข้อมูลในวันที่กำหนด?


141

เป็นไปได้หรือไม่ที่จะสืบค้นวันที่ที่เฉพาะเจาะจง

ฉันพบใน Cookbook mongo ที่เราสามารถทำได้สำหรับช่วงQuerying สำหรับช่วงวันที่ แบบนั้น:

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

แต่มันเป็นไปได้สำหรับวันที่ระบุหรือไม่ สิ่งนี้ใช้ไม่ได้:

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

คำตอบ:


212

สิ่งนี้น่าจะใช้ได้ผลถ้าวันที่คุณบันทึกไว้ในฐานข้อมูลนั้นไม่มีเวลา (แค่ปีเดือนวัน)

โอกาสที่วันที่ที่คุณบันทึกnew Date()รวมถึงองค์ประกอบเวลา ในการค้นหาเวลาเหล่านั้นคุณต้องสร้างช่วงวันที่ที่มีทุกช่วงเวลาในหนึ่งวัน

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

29
โปรดจำไว้ว่าในฟังก์ชั่น Date () อาร์กิวเมนต์เดือนเริ่มนับที่ 0 ไม่ใช่ 1 ในทางกลับกันวันเริ่มนับที่ 1 ... รายละเอียด
Mark Stosberg

ไม่ดีกว่าที่จะทำ _ 1 วันในการรับนัดต่อไปแทนที่จะเป็นรหัสยากทั้งคู่?
raju

2
วิธีนี้ใช้ได้ดีไหมถ้าวันที่เก็บไว้เช่นนี้ >> >> "วันที่": ISODate ("2016-01-04T14: 07: 17.496Z")
santhosh

คุณไม่มีเดือนและวันที่สวิทช์ของคุณ รูปแบบวันที่ควรเป็น: yyyy, dd, MM
thethakuri

123

... 5 ปีขึ้นไปฉันขอแนะนำให้ใช้date-fnsแทน

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

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

สำหรับพวกเราที่ใช้Moment.js

const moment = require('moment')

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

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

สำคัญ: ช่วงเวลาทั้งหมดไม่แน่นอน !

tomorrow = today.add(1, 'days')todayไม่ทำงานเพราะมันยังมีการแปรรูป โทรแก้ว่าปัญหาที่เกิดจากการโคลนนิ่งโดยปริยายmoment(today) today


13
ฉันแนะนำให้ใช้.startOf('day')แทน. ชั่วโมง (0) .minutes (0). วินาที (0) ดังนั้นบรรทัดแรกจะเป็น:var today = moment().startOf('day')
Jim Geurts

2
ถ้าเราใช้moment(today)โคลนวัตถุอีกวิธีคือ:var tomorrow = today.clone().add(1, 'days')
johntellsall

1
@johntellsall การโคลนนิ่งอย่างชัดเจนมากกว่าที่จะบอกเป็นนัยผลลัพธ์เดียวกัน แต่อาจจะง่ายต่อการอ่านแน่นอน!
Pier-Luc Gendreau

1
หรือฉันจะแนะนำต่อไปนี้สำหรับ:$lt moment(today).endOf('day')เพื่อป้องกันไม่ให้ผลลัพธ์ที่แท้จริงรวมในวันถัดไป
greduan

1
สำหรับผมที่จะช่วยให้ในวันเดียวกันกับเวลาที่:moment(today).endOf('day') 23:59:59.999ดังนั้นจริง ๆ แล้วดูถูกต้องมากขึ้นใช้$lteมิฉะนั้นวัตถุในเวลานั้นจะถูกละเว้น
leonprou

11

ใช่วัตถุวันที่จะรวบรวมวันที่และเวลาดังนั้นการเปรียบเทียบกับค่าวันที่จะไม่ทำงาน

คุณสามารถใช้ตัวดำเนินการ$ whereเพื่อแสดงเงื่อนไขที่ซับซ้อนมากขึ้นด้วยนิพจน์บูลีน Javascript :)

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

created_onเป็นฟิลด์ datetime และ2012-07-14เป็นวันที่ที่ระบุ

วันที่ควรจะตรงในYYYY-MM-DDรูปแบบ

หมายเหตุ:ใช้$whereเท่าที่จำเป็นมีผลกระทบด้านประสิทธิภาพ


10

คุณเคยลองไหม:

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

ปัญหาที่คุณจะพบคือวันที่จะถูกเก็บไว้เป็น timestamps ใน Mongo ดังนั้นเพื่อให้ตรงกับวันที่คุณขอให้ตรงกับเวลา ในกรณีของคุณฉันคิดว่าคุณกำลังพยายามจับคู่วัน (เช่นจาก 00:00 น. ถึง 23:59 น. ในวันที่กำหนด) หากวันที่ของคุณถูกเก็บไว้โดยไม่มีเวลาคุณควรจะโอเค มิฉะนั้นลองระบุวันที่ของคุณเป็นช่วงเวลาในวันเดียวกัน (เช่นเริ่ม = 00: 00, สิ้นสุด = 23: 59) หาก gte ใช้งานไม่ได้

คำถามที่คล้ายกัน


1
ซึ่งจะรวมองค์ประกอบทั้งหมดที่อายุน้อยกว่าวันที่ระบุซึ่งอาจไม่ใช่สิ่งที่ OP ต้องการ ลองเพิ่มตัวเลือก "lt" เหมือนกับคำตอบอื่น ๆ
BenSower

ผมคิดว่าถ้าคุณมี$gteแทนgteมันจะดีกว่า
แจ็คว่าง

สิ่งนี้ได้รับคำตอบอย่างถูกต้องมากกว่าด้านบน แต่มันทำให้ฉันรู้ว่าคำตอบของฉันถูกปิดดังนั้นฉันจึงอัปเดตให้ถูกต้องสำหรับคำถาม เฮ้ 4 ปีแล้ว lol
Michael D Johnson

6

คุณสามารถใช้วิธีการต่อไปนี้สำหรับวิธี API เพื่อรับผลลัพธ์ในวันที่กำหนด:

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

เรามีปัญหาเกี่ยวกับข้อมูลที่ซ้ำกันในฐานข้อมูลของเราด้วยฟิลด์วันที่ที่มีค่าหลายค่าที่เราหมายถึงมี 1 ฉันคิดว่าฉันจะเพิ่มวิธีที่เราแก้ไขปัญหานี้เพื่อการอ้างอิง

เรามีชุดข้อมูลที่เรียกว่า "ข้อมูล" พร้อมฟิลด์ "ค่า" ตัวเลขและฟิลด์วันที่ "วันที่" เรามีกระบวนการที่เราคิดว่าเป็น idempotent แต่จบลงด้วยการเพิ่มค่า 2 x ต่อวันในการเรียกใช้ครั้งที่สอง:

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

เราต้องการเพียง 1 ใน 2 ของเรคคอร์ดดังนั้นจึงต้องใช้จาวาสคริปต์เพื่อล้างฐานข้อมูล วิธีการเริ่มต้นของเราคือการทำซ้ำผลลัพธ์และลบฟิลด์ใด ๆ ด้วยเวลาระหว่าง 6.00 น. ถึง 11.00 น. (รายการที่ซ้ำกันทั้งหมดในตอนเช้า) แต่ในระหว่างการดำเนินการทำให้เกิดการเปลี่ยนแปลง นี่คือสคริปต์ที่ใช้ในการแก้ไข:

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

แล้วก็วิ่งไปด้วย mongo thedatabase fixer_script.js

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.