การสืบค้นวันที่ด้วย ISODate ใน mongodb ดูเหมือนจะไม่ทำงาน


189

ฉันดูเหมือนจะไม่ได้รับแม้แต่แบบสอบถามวันที่พื้นฐานที่สุดในการทำงานใน MongoDB ด้วยเอกสารที่มีลักษณะดังนี้:

{
    "_id" : "foobar/201310",
    "ap" : "foobar",
    "dt" : ISODate("2013-10-01T00:00:00.000Z"),
    "tl" : 375439
}

และแบบสอบถามที่มีลักษณะเช่นนี้:

{ 
    "dt" : { 
        "$gte" : { 
            "$date" : "2013-10-01T00:00:00.000Z"
        }
    }
}

ฉันได้รับ0 ผลลัพธ์จากการดำเนินการ:

db.mycollection.find({
  "dt" : { "$gte" : { "$date" : "2013-10-01T00:00:00.000Z"}}
})

ความคิดใด ๆ ที่ว่าทำไมมันถึงไม่ทำงาน?

สำหรับการอ้างอิงการค้นหานี้ถูกสร้างขึ้นโดยMongoTemplate ของ Springดังนั้นฉันจึงไม่สามารถควบคุมการสอบถามที่ส่งไปยัง MongoDB ได้ในที่สุด

(PS)

> db.version()
2.4.7

ขอบคุณ!

คำตอบ:


312

แม้ว่า$dateจะเป็นส่วนหนึ่งของMongoDB Extended JSONและนั่นคือสิ่งที่คุณได้รับเป็นค่าเริ่มต้นด้วยmongoexportฉันไม่คิดว่าคุณสามารถใช้มันเป็นส่วนหนึ่งของแบบสอบถามได้

หากลองค้นหาแบบตรงตาม$dateด้านล่าง:

db.foo.find({dt: {"$date": "2012-01-01T15:00:00.000Z"}})

คุณจะได้รับข้อผิดพลาด:

error: { "$err" : "invalid operator: $date", "code" : 10068 }

ลองสิ่งนี้:

db.mycollection.find({
    "dt" : {"$gte": new Date("2013-10-01T00:00:00.000Z")}
})

หรือ (ติดตามความคิดเห็นโดย@ user3805045 ):

db.mycollection.find({
    "dt" : {"$gte": ISODate("2013-10-01T00:00:00.000Z")}
})

ISODateอาจจำเป็นต้องเปรียบเทียบวันที่โดยไม่มีเวลาด้วย (สังเกตโดย@MattMolnar )

ตามชนิดข้อมูลในเชลล์ mongoทั้งสองควรเทียบเท่า:

mongo shell จัดเตรียมวิธีการต่าง ๆ เพื่อคืนค่าวันที่ไม่ว่าจะเป็นสตริงหรือวัตถุ Date:

  • Date () วิธีการซึ่งจะส่งกลับวันที่ปัจจุบันเป็นสตริง
  • new Date () Constructor ที่ส่งคืนออบเจกต์ Date โดยใช้ ISO wrapper ()
  • ตัวสร้าง ISODate () ซึ่งส่งคืนวัตถุวันที่โดยใช้ตัวห่อหุ้ม ISODate ()

และการใช้ยังคงควรจะกลับวันที่วางวัตถุISODate

{"$date": "ISO-8601 string"}สามารถใช้เมื่อต้องการการแทนค่า JSON ที่เข้มงวด ตัวอย่างหนึ่งที่เป็นไปได้คือตัวเชื่อมต่อ Hadoop


3
ใช่. ฉันคิดว่าฉันถูกโยนออกไปจากสิ่งที่ส่งคืนเมื่อคุณพิมพ์Queryวัตถุในฤดูใบไม้ผลิ รูปแบบที่เป็นอนุกรมของแบบสอบถามไม่จำเป็นต้องเป็นแบบสอบถามที่ถูกต้องที่คุณสามารถคัดลอก / วางลงในเปลือก Mongo ซึ่งในตัวเองเป็นประเภทที่น่าผิดหวัง ผู้ร้ายอยู่ที่นี่: grepcode.com/file/repo1.maven.org/maven2/org.mongodb/ …
Jason Polites

2
เมื่อเปรียบเทียบบางส่วน (ไม่มีเวลา) วันที่ผมต้องเปลี่ยนจากการnew Date('2016-03-09') ISODate('2016-03-09')อดีตจะคืนวันที่ในอดีตสำหรับ$gteแบบสอบถาม
Matt Molnar

@MattMolnar สังเกตและอัปเดตคำตอบพร้อมกับระบุแหล่งที่มา ขอบคุณ
zero323

92

จากความคิดเห็นหน้าตำรา MongoDB :

"dt" : 
{
    "$gte" : ISODate("2014-07-02T00:00:00Z"), 
    "$lt" : ISODate("2014-07-03T00:00:00Z") 
}

สิ่งนี้ใช้ได้สำหรับฉัน ตามบริบททั้งหมดคำสั่งต่อไปนี้จะได้รับทุกระเบียนที่dtเขตข้อมูลวันที่มีวันที่ 2013-10-01 (YYYY-MM-DD) ซูลู:

db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})

1
ฉันได้รับข้อผิดพลาด "ISODate undefined" ฉันไม่สามารถแก้ปัญหานี้ได้
Batuhan Akkaya

@BatuhanAkkaya ในหลามกับ pymongo, เทียบเท่ากับdatetime.datetime ISODate
jtbr


5

ฉันใช้ robomongo เป็นลูกค้า mongodb gui และด้านล่างใช้งานได้สำหรับฉัน

db.collectionName.find({"columnWithDateTime" : {
$lt:new ISODate("2016-02-28T00:00:00.000Z")}})

ในด้านแอพฉันใช้ไดรเวอร์ mongodb (v1.4.3) ซึ่งเป็นโหนดของแอพพลิเคชั่นแอพพลิเคชั่นนั้นใช้ datepicker ใน UI ซึ่งให้วันที่เช่น YYYY-mm-dd นี่จะถูกผนวกเข้ากับเวลาเริ่มต้นเช่น 00:00:00 ไปยังตัวnew Date()สร้างแล้วส่งไปยังวัตถุเกณฑ์ mongodb ฉันคิดว่าคนขับจะแปลงวันที่เป็นวันที่ ISO แล้วแบบสอบถามก็ใช้งานได้และให้ผลลัพธ์ที่ต้องการอย่างไรก็ตามตัวnew Date()สร้างเดียวกันไม่ทำงานหรือแสดงผลลัพธ์เดียวกันบน robo mongo เกณฑ์ซึ่งแปลกเพราะฉันใช้ robomongo เพื่อตรวจสอบวัตถุที่เป็นเกณฑ์ของฉัน

ในขณะที่ cli mongoshell เริ่มต้นทำงานได้ดีกับทั้งสองISODateและnew Date()


1
ขอบคุณสำหรับเคล็ดลับ Robomongo ดีกว่า Mongo Compass
Alex

5

ในโหมดเข้มงวด json คุณจะต้องรักษาลำดับ:

{
    "dt": {
        "$gte": {
            "$date": "2013-10-01T00:00:00.000Z"
        }
    }
}

สิ่งเดียวที่ทำงานเพื่อกำหนดคำค้นหาของฉันใน mlab.com


เกิดข้อผิดพลาดในการเรียกใช้คิวรี เหตุผล: (invalid_operator) ผู้ประกอบการที่ไม่ถูกต้อง: $ date
saber tabatabaee yazdi

2

ในเปลือก MongoDB:

db.getCollection('sensorevents').find({from:{$gt: new ISODate('2015-08-30 16:50:24.481Z')}})

ในรหัส nodeJS ของฉัน (ใช้ Mongoose)

    SensorEvent.Model.find( {
        from: { $gt: new Date( SensorEventListener.lastSeenSensorFrom ) }
    } )

ฉันกำลังค้นหาคอลเลกชันเหตุการณ์เซ็นเซอร์ของฉันเพื่อส่งคืนค่าที่ฟิลด์ 'จาก' มากกว่าวันที่กำหนด


4
ยินดีต้อนรับสู่ Stack Overflow! กรุณาโพสต์คำตอบสำหรับคำถามไม่ใช่สิ่งพิเศษเช่น "นี่คือโพสต์แรกของฉัน" คิดว่า Stack Overflow เป็น Wikipedia ไม่ใช่กระดานข้อความ
durron597

1

นี่คือเอกสารของฉัน

"_id" : ObjectId("590173023c488e9a48e903d6"),
    "updatedAt" : ISODate("2017-04-27T04:26:42.709Z"),
    "createdAt" : ISODate("2017-04-27T04:26:42.709Z"),
    "flightId" : "590170f97cb84116075e2680",

 "_id" : ObjectId("590173023c488e9a48e903d6"),
        "updatedAt" : ISODate("2017-04-28T03:26:42.609Z"),
        "createdAt" : ISODate("2017-04-28T03:26:42.609Z"),
        "flightId" : "590170f97cb84116075e2680",

ตอนนี้ฉันต้องการค้นหาทุก ๆ วันที่ 27 ดังนั้นฉันจึงใช้สิ่งนี้ ....

 > db.users.find({createdAt:{"$gte":ISODate("2017-04-27T00:00:00Z"),"$lt":ISODate("2017-04-28T00:00:00Z") }}).count()

result:1

สิ่งนี้ใช้ได้สำหรับฉัน


0

สิ่งนี้ใช้ได้กับฉันในขณะที่ค้นหาค่าน้อยกว่าหรือเท่ากับตอนนี้:

db.collectionName.find({ "dt": { "$lte" : new Date() + "" } });


0

คำถามเก่า แต่ยังเป็น google hit ครั้งแรกดังนั้นฉันโพสต์ที่นี่ดังนั้นฉันพบมันได้ง่ายขึ้นอีกครั้ง ...

ใช้ Mongo 4.2 และมวลรวม ():

db.collection.aggregate(
    [
     { $match: { "end_time": { "$gt": ISODate("2020-01-01T00:00:00.000Z")  } } },
     { $project: {
          "end_day": { $dateFromParts: { 'year' : {$year:"$end_time"}, 'month' : {$month:"$end_time"}, 'day': {$dayOfMonth:"$end_time"}, 'hour' : 0  } }
     }}, 
     {$group:{
        _id:   "$end_day",
        "count":{$sum:1},
    }}
   ]
)

อันนี้ให้ตัวแปร groupby เป็นวันที่บางครั้งดีกว่าที่จะเป็นส่วนประกอบเอง

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