简体   繁体   English

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

[英]Can I query MongoDB ObjectId by date?

I know that ObjectIds contain the date they were created on.我知道 ObjectIds 包含它们的创建日期。 Is there a way to query this aspect of the ObjectId?有没有办法查询ObjectId的这个方面?

Popping Timestamps into ObjectIds covers queries based on dates embedded in the ObjectId in great detail. Popping Timestamps into ObjectIds涵盖了基于嵌入在 ObjectId 中的日期的非常详细的查询。

Briefly in JavaScript code:在 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') } });

In pymongo , it can be done this way: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}}))

Using inbuilt function provided by mongodb drivers in in Node.js lets you query by any timestamp:在 Node.js 中使用 mongodb 驱动程序提供的内置函数可以让您按任何时间戳查询:

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

Alternatively, to search for records before the current time, you can simply do:或者,要搜索当前时间之前的记录,您只需执行以下操作:

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

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

You can use $convert function to extract the date from ObjectId starting in 4.0 version.从 4.0 版本开始,您可以使用$convert函数从 ObjectId 中提取日期。

Something like就像是

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

You can query on date comparing between start and end time for 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")]}
    ]
  }
})

OR或者

You can use shorthand $toDate to achieve the same.您可以使用速记$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")]}
    ]
  }
})

how to find Find the Command (this date[2015-1-12] to this Date[2015-1-15] ):如何找到查找命令(这个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()

Count the Command (this date[2015-1-12] to this Date[2015-1-15] ):计算命令(这个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")
  }
})

Remove the Command (this date[2015-1-12] to this Date[2015-1-15] ):删除命令(这个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")
  }
})

Since the first 4 bytes of an ObjectId represent a timestamp , to query your collection chronologically, simply order by id:由于 ObjectId 的前 4 个字节表示时间戳,要按时间顺序查询您的集合,只需按 id 排序:

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

After you get the documents, you can get the ObjectId's generation time like so:获取文档后,您可以像这样获取 ObjectId 的生成时间

id = some_object_id
generation_time = id.generation_time

为了在 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" )}})

If you want to make a range query, you can do it like in this post .如果你想进行范围查询,你可以像这篇文章中那样做。 For example querying for a specific day (ie Apr 4th 2015):例如查询特定日期(即 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()

From the documentation:从文档:

o = new ObjectId()
date = o.getTimestamp()

this way you have date that is a ISODate.这样你就有了一个 ISODate 的日期。

Look at http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs#OptimizingObjectIDs-Extractinsertiontimesfromidratherthanhavingaseparatetimestampfield .查看http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs#OptimizingObjectIDs-Extractinsertiontimesfromidratherthanhaveaseparatetimestampfield for more information想要查询更多的信息

使用 MongoObjectID 您还应该找到如下所示的结果

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

Yes you can query object by date using MongoDB inserted ID是的,您可以使用 MongoDB 插入的 ID 按日期查询对象

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

let's suppose users is my collection and I want all users created less than 05 January 2018让我们假设 users 是我的集合,我希望所有用户创建于 2018 年 1 月 5 日以内

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

For running from a query we can use like对于从查询运行,我们可以使用像

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

All the users from the current time - 3 hours当前时间的所有用户 - 3 小时

In rails mongoid you can query using在 rails mongoid您可以使用查询

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

A Solution Filtering within MongoDB Compass. MongoDB Compass 中的解决方案过滤。

Based on versions:基于版本:

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

Option 1:选项1:

@s7vr 's answer worked perfectly for me. @s7vr 的回答对我来说非常有效。 You can paste this into the Filter field:您可以将其粘贴到过滤器字段中:

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

Option 2:选项 2:

I also found this to work (remember that the Date's month parameter is 0-based indexing so January is 0):我也发现这个工作(记住日期的月份参数是基于 0 的索引,所以一月是 0):

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

Option 3:选项 3:

Equivalent with ISODate:等效于 ISODate:

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

After writing this post, I decided to run the Explain on these queries.写完这篇文章后,我决定对这些查询运行解释。 Here's the skinny on performance:这是性能方面的薄弱环节:

  • Option 1 : 39 ms, 0 indexes used, 30 ms in COLLSCAN选项1:39 毫秒,使用 0 个索引,在 COLLSCAN 中为 30 毫秒
  • Option 2 : 0 ms, _id index used选项 2 :0 毫秒,使用_id索引
  • Option 3 : 1 ms, _id index used, 1 ms in FETCH选项 3 :1 毫秒,使用_id索引,在 FETCH 中为 1 毫秒

Based on my rudimentary analysis, it appears that option 2 is the most efficient.根据我的初步分析,选项 2 似乎是最有效的。 I will use Option 3, personally, as it is a little cleaner to use ISODate rather than remembering 0-based month indexing in the Date object.我个人将使用选项 3,因为使用 ISODate 而不是记住 Date 对象中基于 0 的月份索引会更简洁一些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM