รับรายการที่แทรกล่าสุดต่อวัน

มีคุณสมบัติใน mongodb ที่ฉันสามารถใช้เพื่อรับรายการที่แทรกล่าสุดต่อวันหรือไม่? ฉันมีคอลเลกชันที่ฉันต้องการรับรายการที่แทรกล่าสุดต่อวัน ข้อมูลจะถูกจัดกลุ่มเป็นรายชั่วโมงตามโครงสร้างด้านล่าง

{
   timestamp: 2017-05-04T09:00:00.000+0000,
   data: {}
},
{
   timestamp: 2017-05-04T10:00:00.000+0000,
   data: {}
}

ฉันคิดจะใช้เครื่องฉายภาพแต่ฉันไม่แน่ใจว่าจะทำสิ่งนี้ได้อย่างไร

แก้ไข: นอกจากนี้ เนื่องจาก mongodb เก็บข้อมูลใน UTC ฉันจึงต้องบัญชีออฟเซ็ตด้วย


person Bazinga777    schedule 06.06.2017    source แหล่งที่มา
comment
ขั้นแรก จัดเรียงข้อมูลตามการประทับเวลา (จากเก่าที่สุดไปหาใหม่ที่สุด) จากนั้น จัดกลุ่มเอกสารตามวัน ( ในระยะ $group ) และเก็บ data สุดท้ายไว้กับ $last   -  person felix    schedule 06.06.2017


คำตอบ (1)


คุณสามารถ $sort และใช้ $last สำหรับรายการ โดยปัดเศษคีย์การจัดกลุ่มในแต่ละวัน:

db.collection.aggregate([
  { "$sort": { "timestamp": 1 } },
  { "$group": {
     "_id": {
       "$add": [
         { "$subtract": [
           { "$subtract": [ "$timestamp", new Date(0) ] },
           { "$mod": [
             { "$subtract": [ "$timestamp", new Date(0) ] },
             1000 * 60 * 60 * 24
           ]}
         ]},
         new Date(0)
       ]
     },
     "lastDoc": { "$last": "$$ROOT" }
  }}
])

ดังนั้นการจัดเรียงจะทำให้สิ่งต่างๆ ปรากฏตามลำดับ จากนั้นกลุ่ม _id จะถูกปัดเศษในแต่ละวันด้วยคณิตศาสตร์วันที่ คุณลบวันที่ยุคออกจากวันที่ปัจจุบันเพื่อให้เป็นตัวเลข ใช้โมดูลัสเพื่อปัดเศษเป็นวัน จากนั้นเพิ่มวันที่ยุคให้เป็นตัวเลขเพื่อส่งกลับ Date

เมื่อพิจารณาทางคณิตศาสตร์แล้ว เราได้ค่าการประทับเวลาจากวันที่ที่มีเส้น $subract เราทำสิ่งนี้สองสามครั้ง:

{ "$subtract": [ "$timestamp", new Date(0) ] }

// Is roughly internally like
ISODate("2017-06-06T10:44:37.627Z") - ISODate("1970-01-01T00:00:00Z")
1496745877627

จากนั้นจะมีโมดูโลที่มี $mod ซึ่งเมื่อนำไปใช้กับค่าตัวเลขจะส่งกลับค่าความแตกต่าง 1,000 มิลลิวินาที * 60 วินาที * 60 * นาที * 24 ชั่วโมงให้อาร์กิวเมนต์อื่น:

 { "$mod": [
   { "$subtract": [ "$timestamp", new Date(0) ] },
   1000 * 60 * 60 * 24
 ]}

 // Equivalent to 
 1496745877627 % (1000 * 60 * 60 * 24)
 38677627

จากนั้นจะมีการล้อม $subtract ของตัวเลขทั้งสอง:

 { "$subtract": [
   { "$subtract": [ "$timestamp", new Date(0) ] },
   { "$mod": [
     { "$subtract": [ "$timestamp", new Date(0) ] },
     1000 * 60 * 60 * 24
   ]}
 ]}

 // Subtract "difference" of the modulo to a day
 // from the milliseconds value of the current date
 1496745877627 - 38677627

 1496707200000

จากนั้นเพิ่มกลับไปที่ค่าวันที่ของยุคเพื่อสร้างวันที่ที่ปัดเศษเป็นวันปัจจุบัน ซึ่งโดยทั่วไปแล้วไปป์ไลน์การรวมจะดูเหมือนว่าจะให้ค่ามิลลิวินาทีแก่ตัวสร้าง:

new Date(1496707200000)
ISODate("2017-06-06T00:00:00Z")

ซึ่งใช้ค่าการประทับเวลาและลบส่วนต่างของตัวหารออกจาก "หนึ่งวัน" และจบลงที่เวลาที่ "เริ่มต้นของวัน"

เพียงใช้ $$ROOT ที่นี่เพื่อแสดงเอกสารทั้งหมด แต่เส้นทางเอกสารใดๆ ที่ให้ไว้กับ $last ที่นี่จะให้ผลลัพธ์

person Neil Lunn    schedule 06.06.2017
comment
ขอบคุณ แต่ช่วยอธิบายกระบวนการจัดกลุ่มเพิ่มเติมอีกหน่อยได้ไหม มันได้ผลจริงๆ หลังจากที่ฉันแทนที่ตัวเลขทั้งหมดด้วยตัวเลขตัวเดียว - person Bazinga777; 06.06.2017
comment
@ Bazinga777 มันไม่ควรสร้างความแตกต่างจริงๆ ทำงานได้ดีสำหรับฉันใน JavaScript และฉันก็ทำมันตลอดเวลา คณิตศาสตร์ทำงานอย่างไรในการปัดเศษให้เป็นวันที่คุณต้องเข้าใจดีกว่าคำอธิบายปัจจุบัน - person Neil Lunn; 06.06.2017
comment
ประเด็นคือฉันต้องเพิ่มออฟเซ็ตสำหรับแต่ละเขตเวลา ฉันพลาดสิ่งนั้นในคำถามของฉัน - person Bazinga777; 06.06.2017
comment
จริงๆ ฉันอยากรู้คณิตศาสตร์ - person Bazinga777; 06.06.2017
comment
@Bazinga777 โอเค มันใช้เวลานานมากเท่าที่ฉันจะสามารถทำได้โดยไม่ต้องฟังบรรยาย หวังว่าคุณจะเรียนรู้บางสิ่งบางอย่าง ดังนั้นการชดเชยเขตเวลาของคุณควรอยู่ในตำแหน่งที่คุณกำลังแปลงการประทับเวลาปัจจุบันจากประเภท Date BSON เป็นประเภทตัวเลข ดังนั้นในบรรทัดเดียวกับที่ใช้คำสั่ง $subtract ซ้ำ ทำแบบนั้นตลอดเช่นกัน - person Neil Lunn; 06.06.2017
comment
ขอบคุณมากสำหรับเรื่องนี้. ตอนนี้ฉันเข้าใจวิธีบัญชีชดเชยแล้วด้วย - person Bazinga777; 06.06.2017
comment
@ Bazinga777 ดีสำหรับคุณ จริงๆ แล้วฉันมีโค้ดบางตัวที่คำนึงถึงการเปลี่ยนแปลงในเวลาออมแสงด้วย และสร้างการคำนวณที่แตกต่างกันผ่าน $cond โดยกำหนดช่วงวันที่ที่ข้ามการเปลี่ยนแปลงที่ไหนสักแห่ง ฉันคิดว่ามีคำตอบลอยอยู่ตรงนี้ซึ่งฉันแสดงให้เห็นแล้ว แต่ดูเหมือนจะหาไม่พบ อย่างไรก็ตาม อย่างน้อยคุณก็มีสิ่งที่คุณต้องการในตอนนี้ - person Neil Lunn; 06.06.2017
comment
ฉันจะขอบคุณทรัพยากรใด ๆ - person Bazinga777; 06.06.2017