Tôi có thể truy vấn MongoDB ObjectId theo ngày không?


Câu trả lời:


224

Dấu thời gian bật vào ObjectIds bao gồm các truy vấn dựa trên ngày được nhúng trong ObjectId rất chi tiết.

Tóm tắt bằng mã JavaScript:

/* This function returns an ObjectId embedded with a given datetime */
/* Accepts both Date object and string input */

function objectIdWithTimestamp(timestamp) {
    /* Convert string date to Date object (otherwise assume timestamp is a date) */
    if (typeof(timestamp) == 'string') {
        timestamp = new Date(timestamp);
    }

    /* Convert date object to hex seconds since Unix epoch */
    var hexSeconds = Math.floor(timestamp/1000).toString(16);

    /* Create an ObjectId with that hex timestamp */
    var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");

    return constructedObjectId
}


/* Find all documents created after midnight on May 25th, 1980 */
db.mycollection.find({ _id: { $gt: objectIdWithTimestamp('1980/05/25') } });

29
Rất tiện dụng .. FYI, bạn có thể lưu chức năng này trong ~/.mongorc.jstệp của mình để có sẵn khi trình mongobao khởi động.
Stennie

1
Tôi nhận được ReferenceError: ObjectId không được xác định. Làm thế nào để tôi sửa nó?
peter

3
Tôi đang sử dụng nodejs với mongodbnative. Đã sửa lỗi "lỗi không xác định" bằng cách bao gồm var ObjectId = quiries ('mongodb'). ObjectID;
peter

1
Nếu bạn đang sử dụng Mongoskin như tôi: Thay đổi ObjectId(hexSeconds + "0000000000000000");thànhdb.ObjectID.createFromHexString(hexSeconds + "0000000000000000");
Anders stman

2
Hoặc, trong Mongoose, thay thế ObjectId()bằng: require('mongoose').Types.ObjectId()- require('mongoose')trường hợp Mongoose được khởi tạo / cấu hình của bạn ở đâu .
toblerpwn

34

Sử dụng hàm inbuilt được cung cấp bởi trình điều khiển mongodb trong Node.js cho phép bạn truy vấn bằng bất kỳ dấu thời gian nào:

var timestamp = Date.now();
var objectId = ObjectID.createFromTime(timestamp / 1000);

Ngoài ra, để tìm kiếm các bản ghi trước thời điểm hiện tại, bạn chỉ cần làm:

var objectId = new ObjectID(); // or ObjectId in the mongo shell

Nguồn: http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html


3
Đây là cách tốt nhất / dễ nhất để tạo ObjectId từ dấu thời gian trong env javascript. Đó là những gì mà op yêu cầu ...
Anders stman

34

Trong pymongo, nó có thể được thực hiện theo cách này:

import datetime
from bson.objectid import ObjectId
mins = 15
gen_time = datetime.datetime.today() - datetime.timedelta(mins=mins) 
dummy_id = ObjectId.from_datetime(gen_time)
result = list(db.coll.find({"_id": {"$gte": dummy_id}}))

Lưu ý sử dụng datetime.datetime.utcnow () hoặc datetime.datetime.today () sẽ trả về kết quả tương tự. Thời gian được xử lý cho bạn.
radtek

Ngoài ra, không sử dụng pymongophụ thuộc: epoch_time_hex = format(int(time.time()), 'x') (đừng quên nối các số 0 cho truy vấn của bạn) Gói thời gian đã được sử dụng ( import time).
VasiliNovikov

Nhận ra OP đã yêu cầu javascript, nhưng điều này thực sự giúp tôi đơn giản hóa mã của mình. Cảm ơn.
Fred S

14

Vì 4 byte đầu tiên của ObjectId đại diện cho dấu thời gian , để truy vấn bộ sưu tập của bạn theo trình tự thời gian, chỉ cần sắp xếp theo id:

# oldest first; use pymongo.DESCENDING for most recent first
items = db.your_collection.find().sort("_id", pymongo.ASCENDING)

Sau khi bạn nhận được tài liệu, bạn có thể có được thời gian tạo thế hệ của ObjectId như sau:

id = some_object_id
generation_time = id.generation_time

1
Tôi đã hy vọng điều gì đó thực sự sẽ cho phép thực hiện những việc như lấy số lượng đối tượng được tạo trước một thời gian nhất định bằng cách sử dụng thời gian được nhúng trong ObjectId, nhưng có vẻ như điều đó không thể truy cập trực tiếp. Cảm ơn.
Zach

1
Bạn có thể làm điều đó, nhìn vào câu trả lời của Leftium.
atp

13

Cách tìm Tìm Lệnh (ngày này [2015-1-12] đến Ngày này [2015-1-15]):

db.collection.find ({_ id: {$ gt: ObjectId (Math.floor ((Ngày mới ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((Ngày mới ('2015/1/15')) / 1000) .toString (16) + "0000000000000000")}}). Khá ()

Đếm Lệnh (ngày này [2015-1-12] đến Ngày này [2015-1-15]):

db.collection.count ({_ id: {$ gt: ObjectId (Math.floor ((Ngày mới ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((Ngày mới ('2015/1/15')) / 1000) .toString (16) + "0000000000000000")}})

Xóa Lệnh (ngày này [2015-1-12] đến Ngày này [2015-1-15]):

db.collection.remove ({_ id: {$ gt: ObjectId (Math.floor ((Ngày mới ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((Ngày mới ('2015/1/15')) / 1000) .toString (16) + "0000000000000000")}})


10

Bạn có thể dùng $convert chức năng để trích xuất ngày từ ObjectId bắt đầu từ phiên bản 4.0.

Cái gì đó như

$convert: { input: "$_id", to: "date" } 

Bạn có thể truy vấn vào ngày so sánh giữa thời gian bắt đầu và kết thúc cho ngày.

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

HOẶC LÀ

Bạn có thể sử dụng tốc ký $toDateđể đạt được điều tương tự.

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$toDate":"$_id"}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$toDate":"$_id"},ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

Chỉ muốn hỏi khi sử dụng $ convert OR $ toDate, trước tiên Mongo sẽ phải chuyển đổi và sau đó so sánh liệu doc ​​có hiện diện trong phạm vi hay không, nhưng nếu tôi sử dụng phương pháp trả lời được chấp nhận thì chuyển đổi ngày thành ObjectId tôi sẽ chỉ phải làm về phía khách hàng và chỉ một lần, vậy bạn có nghĩ rằng giải pháp đó sẽ hiệu quả hơn thế này không? dù sao cũng cảm ơn vì đã nói rằng hai nhà khai thác này cũng tồn tại :)
Sudhanshu Bò tót

7

Để có được tài liệu cũ 60 ngày qua trong bộ sưu tập mongo tôi đã sử dụng bên dưới truy vấn trong shell.

db.collection.find({_id: {$lt:new ObjectId( Math.floor(new Date(new Date()-1000*60*60*24*60).getTime()/1000).toString(16) + "0000000000000000" )}})

1
Sử dụng $ gt thay vì $ lt. Mặt khác, nó tìm thấy các tài liệu được chèn trước đó (hôm nay - 60 ngày).
yoooshi

1
@Vivek 4 byte đầu tiên của ObjectId đại diện cho số giây kể từ kỷ nguyên unix (1970/1/1 00:00:00 UTC) và như vậy bạn có thể sử dụng nó với giá trị lớn hơn ($ gt) và nhỏ hơn ($ lt) để tìm các đối tượng được tạo trong một cửa sổ nhất định.
John

5

Nếu bạn muốn thực hiện một truy vấn phạm vi, bạn có thể làm điều đó như trong bài viết này . Ví dụ: truy vấn cho một ngày cụ thể (ví dụ: ngày 4 tháng 4 năm 2015):

> var objIdMin = ObjectId(Math.floor((new Date('2015/4/4'))/1000).toString(16) + "0000000000000000")
> var objIdMax = ObjectId(Math.floor((new Date('2015/4/5'))/1000).toString(16) + "0000000000000000")
> db.collection.find({_id:{$gt: objIdMin, $lt: objIdMax}}).pretty()


2

Sử dụng MongoObjectID, bạn cũng sẽ tìm thấy kết quả như được đưa ra dưới đây

db.mycollection.find({ _id: { $gt: ObjectId("5217a543dd99a6d9e0f74702").getTimestamp().getTime()}});

3
câu lệnh truy vấn của bạn giả sử người ta biết giá trị ObjectId để bắt đầu mà không phải lúc nào cũng như vậy.
Dwight Spencer

0

Trong đường ray, mongoidbạn có thể truy vấn bằng cách sử dụng

  time = Time.utc(2010, 1, 1)
  time_id = ObjectId.from_time(time)
  collection.find({'_id' => {'$lt' => time_id}})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.