我可以按日期查询 MongoDB ObjectId 吗?

我知道 ObjectID 包含创建它们的日期。有办法查询 ObjectId 的这个方面吗?

106211 次浏览

由于 ObjectId 表示时间戳的前4个字节,要按时间顺序查询集合,只需按 id 排序:

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

获取文档之后,可以像下面这样获取 ObjectId 的 一代人的时间:

id = some_object_id
generation_time = id.generation_time

将时间戳弹出到 ObjectId 中将详细介绍基于 ObjectId 中嵌入的日期的查询。

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

使用 MongoObjectID,您还应该找到下面给出的结果

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

在 Node.js 中使用 mongodb 驱动程序提供的内置函数,可以根据任何时间戳进行查询:

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

或者,要在当前时间之前搜索记录,您可以简单地这样做:

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

资料来源: http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html

pymongo中,可以这样做:

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

为了在 mongo 集合中获得最后60天的旧文档,我在 shell 中使用了以下查询。

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

如果要进行范围查询,可以像在 这篇文章中那样进行。例如查询某一天(即2015年4月4日) :

> 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()

如何查找 Find the Command (从这个 date[2015-1-12]到这个 Date[2015-1-15]) :

db.collection.find({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
}).pretty()

计算命令(从这个 date[2015-1-12]到这个 Date[2015-1-15]) :

db.collection.count({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
})

删除命令(这个 date[2015-1-12]到这个 Date[2015-1-15]) :

db.collection.remove({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
})

可以使用 $convert函数从4.0版本的 ObjectId 中提取日期。

差不多

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

可以查询开始时间和结束时间之间的日期。

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")]}
]
}
})

或者

您可以使用简写 $toDate来实现相同的功能。

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")]}
]
}
})

在 Rails mongoid中,可以使用

  time = Time.utc(2010, 1, 1)
time_id = ObjectId.from_time(time)
collection.find({'_id' => {'$lt' => time_id}})

是的,您可以使用 MongoDB 插入的 ID 按日期查询对象

db.collectionname.find({_id: {$lt: ObjectId.fromDate( new ISODate("TZformat") ) } });

让我们假设用户是我的集合,我希望所有用户创建小于052018年1月

db.users.find({_id: {$lt: ObjectId.fromDate( new ISODate("2018-01-05T00:00:00.000Z") ) } });

对于从查询运行,我们可以使用

db.users.find({_id: {$lt: ObjectId.fromDate(new Date((new Date().getTime() - (1 * 3 * 60 * 60 * 1000))) ) } })

所有用户从当前时间-3小时

MongoDB 指南针中的解决方案过滤。

基于版本:

  • 指南针版本: 1.25.0
  • MongoDB 版本: 4.2.8

选择1:

@ s7vr 的回答对我来说非常有效。你可以把这个粘贴到 Filter 字段:

{$expr: { $and: [ {$gte: [{$toDate: "$_id"}, ISODate('2021-01-01')]}, {$lt: [{$toDate: "$_id"}, ISODate('2021-02-01')]} ] } }

选择2:

我还发现这种方法是有效的(请记住 Date 的 month 参数是基于0的索引,所以 January 是0) :

{_id: {$gte: ObjectId(Date(2021, 0, 1) / 1000), $lt: ObjectId(Date(2021, 1, 1) / 1000) } }

选择3:

相当于 ISODate:

{_id: {$gte: ObjectId(ISODate('2021-01-01') / 1000), $lt: ObjectId(Date('2021-02-01') / 1000) } }

写完这篇文章后,我决定对这些问题进行解释:

  • 选项1 : 使用39ms,0索引,COLLSCAN 中使用30ms
  • 选项2 : 0 ms,使用 身份证指数
  • 选项3 : 1ms,使用 身份证指数,在 FETCH 中使用1ms

根据我的初步分析,选项2似乎是最有效的。我个人将使用选项3,因为使用 ISODate 比在 Date 对象中记住基于0的月份索引要干净一些。