用于 mongodb ObjectId 创建时间

发布于 2024-10-19 02:39:27 字数 157 浏览 2 评论 0原文

mongodb 文档中用作默认键的 ObjectId 嵌入了时间戳(调用 objectid. Generation_time 返回一个日期时间对象)。那么是否可以使用这个生成时间而不是保留单独的创建时间戳?您如何能够使用此嵌入时间戳按创建时间排序或有效查询最后 N 个项目?

The ObjectId used as the default key in mongodb documents has embedded timestamp (calling objectid.generation_time returns a datetime object). So it is possible to use this generation time instead of keeping a separate creation timestamp? How will you be able to sort by creation time or query for the last N items efficiently using this embedded timestamp?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

御守 2024-10-26 02:39:27

我想由于 MongoDB ObjectId 包含时间戳,如果您要按 objectId 排序,则可以按“创建日期”排序:

items.find.sort( [['_id', -1]] ) // get all items desc by created date.

如果您想要最后 30 个创建的项目,您可以使用以下查询:

items.find.sort( [['_id', -1]] ).limit(30) // get last 30 createad items 

我实际上不确定,我只是假设排序_id 应按上述方式工作。稍后我将创建一些测试。

更新:

是的,确实如此。如果您按 _id 订购,您将自动按 _id 创建日期订购。
我在 C# 中做了一个小测试,mb 有人对此感兴趣:

  public class Item
  {
    [BsonId]
    public ObjectId Id { get; set; }

    public DateTime CreatedDate { get; set; }

    public int Index { get; set; }
  }



 [TestMethod]
 public void IdSortingTest()
 {
   var server = MongoServer.Create("mongodb://localhost:27020");
   var database = server.GetDatabase("tesdb");

   var collection = database.GetCollection("idSortTest");
   collection.RemoveAll();

   for (int i = 0; i <= 500; i++)
   {
     collection.Insert(new Item() { 
             Id = ObjectId.GenerateNewId(), 
             CreatedDate = DateTime.Now, 
             Index = i });
   }

   var cursor = collection.FindAllAs<Item>();
   cursor.SetSortOrder(SortBy.Descending("_id"));
   var itemsOrderedById = cursor.ToList();

   var cursor2 = collection.FindAllAs<Item>();
   cursor2.SetSortOrder(SortBy.Descending("CreatedDate"));
   var itemsOrderedCreatedDate = cursor.ToList();

   for (int i = 0; i <= 500; i++)
   {
     Assert.AreEqual(itemsOrderedById[i].Index, itemsOrderedCreatedDate[i].Index);
   }
}

I suppose since MongoDB ObjectId contain a timestamp, you can sort by 'created date' if you will sort by objectId:

items.find.sort( [['_id', -1]] ) // get all items desc by created date.

And if you want last 30 created items you can use following query:

items.find.sort( [['_id', -1]] ).limit(30) // get last 30 createad items 

I am actualy not sure,i just suppose that ordering by _id should work as described above. I'll create some tests later.

Update:

Yes it is so. If you order by _id you will automatically order by _id created date.
I've done small test in c#, mb someone interest in it:

  public class Item
  {
    [BsonId]
    public ObjectId Id { get; set; }

    public DateTime CreatedDate { get; set; }

    public int Index { get; set; }
  }



 [TestMethod]
 public void IdSortingTest()
 {
   var server = MongoServer.Create("mongodb://localhost:27020");
   var database = server.GetDatabase("tesdb");

   var collection = database.GetCollection("idSortTest");
   collection.RemoveAll();

   for (int i = 0; i <= 500; i++)
   {
     collection.Insert(new Item() { 
             Id = ObjectId.GenerateNewId(), 
             CreatedDate = DateTime.Now, 
             Index = i });
   }

   var cursor = collection.FindAllAs<Item>();
   cursor.SetSortOrder(SortBy.Descending("_id"));
   var itemsOrderedById = cursor.ToList();

   var cursor2 = collection.FindAllAs<Item>();
   cursor2.SetSortOrder(SortBy.Descending("CreatedDate"));
   var itemsOrderedCreatedDate = cursor.ToList();

   for (int i = 0; i <= 500; i++)
   {
     Assert.AreEqual(itemsOrderedById[i].Index, itemsOrderedCreatedDate[i].Index);
   }
}
柠檬色的秋千 2024-10-26 02:39:27

是的,您可以将 BSON ObjectId 的 Generation_time 用于您想要的目的。因此,

db.collection.find().sort({ _id : -1 }).limit(10)

将返回最后 10 个创建的项目。但是,由于嵌入的时间戳具有一秒的精度,因此任何一秒内的多个项目都按其创建顺序存储。

Yes, you can use the generation_time of BSON ObjectId for the purposes you want. So,

db.collection.find().sort({ _id : -1 }).limit(10)

will return the last 10 created items. However, since the embedded timestamps have a one second precision, multiple items within any second are stored in the order of their creation.

七月上 2024-10-26 02:39:27

使用 C# 驱动程序将 DateTime 转换为其相应时间戳的代码如下:

    public static ObjectId ToObjectId(this DateTime dateTime)
    {
        var timestamp = (int)(dateTime - BsonConstants.UnixEpoch).TotalSeconds;
        return new ObjectId(timestamp, 0, 0, 0);
    }

更多信息:http://www.danharman.net/2011/10/26/mongodb-ninjitsu-using-objectid-as-a-timestamp/

The code to convert a DateTime to its corresponding timestamp with the c# driver is as follows:

    public static ObjectId ToObjectId(this DateTime dateTime)
    {
        var timestamp = (int)(dateTime - BsonConstants.UnixEpoch).TotalSeconds;
        return new ObjectId(timestamp, 0, 0, 0);
    }

More info here: http://www.danharman.net/2011/10/26/mongodb-ninjitsu-using-objectid-as-a-timestamp/

野の 2024-10-26 02:39:27

来自: http://www.mongodb.org/display/DOCS/Object +IDs#ObjectIDs-DocumentTimestamps

“对存储 ObjectId 值的 _id 字段进行排序大致相当于按创建时间排序,尽管这种关系对于一秒内在多个系统上生成的 ObjectId 值并不严格。”

From: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-DocumentTimestamps

"sorting on an _id field that stores ObjectId values is roughly equivalent to sorting by creation time, although this relationship is not strict with ObjectId values generated on multiple systems within a single second."

So要识趣 2024-10-26 02:39:27

请参阅

http://www.mongodb.org/display/DOCS/Object+ IDs#ObjectIDs-DocumentTimestamps

可能是可行的,但是我总是更喜欢有一个专用的时间戳,而不是依赖于一些这样的内部结构,比如以某种方式嵌入到某个对象 ID 中的时间戳。

See

http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-DocumentTimestamps

Likely doable however I would always prefer having a dedicated timestamp instead of relying on some such internals like timestamp somehow embedded in some object id.

温柔一刀 2024-10-26 02:39:27

要查询 7 天内创建的项目,我使用下面的代码片段:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
})

如果您想获取具有指定字段的项目:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
}).toArray().map(function(item) {
  var res = {};
  res['Project Name'] = item.config.label;
  res['Author'] = item.author;
  res['Created At'] = item._id.getTimestamp().toLocaleDateString();
  res['Last Modified Date'] = item.config.lastModifDate.toLocaleString();
  return res;
});

它将返回类似这样的内容:

[{
  "Project Name": "Newsletter",
  "Author": "larry.chen",
  "Created At": "Thursday, January 19, 2017",
  "Last Modified Date": "Thursday, January 19, 2017 17:05:40"
}...]

PS:我的软件用于连接 MongoDB 的是 Robo 3T

希望这会对您有所帮助。

To query projects created within 7 days, I use below snippet:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
})

and if you want to get items with specified fields:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
}).toArray().map(function(item) {
  var res = {};
  res['Project Name'] = item.config.label;
  res['Author'] = item.author;
  res['Created At'] = item._id.getTimestamp().toLocaleDateString();
  res['Last Modified Date'] = item.config.lastModifDate.toLocaleString();
  return res;
});

it will return something like this:

[{
  "Project Name": "Newsletter",
  "Author": "larry.chen",
  "Created At": "Thursday, January 19, 2017",
  "Last Modified Date": "Thursday, January 19, 2017 17:05:40"
}...]

PS: the software I use to connect to MongoDB is Robo 3T

Hope this will help you.

香草可樂 2024-10-26 02:39:27

对于那些想要真正将 ObjectId 用于日期时间的人,而不仅仅依赖于 ObjectId 总是随时间增加这一事实,因此可以用于通过创建时间间接对文档进行排序,那么可以这样做:

可以创建过滤条件来返回文档其 ID 是通过创建虚拟 ObjectID.from_datetime() 在某个日期时间范围内(在 Python 中)创建的,如下所示:

# gets docs which were created in last 5 minutes
resp = await collection.update_one({'_id': {'$gte': ObjectId.from_datetime(datetime.utcnow() - timedelta(minutes=5))}},

For those wanting to truly use ObjectId for datetime, and not just rely on the fact that ObjectId's are always increasing over time and can therefore be used to order documents by creation time indirection, then here's how:

One can create their filter criteria to return documents whose IDs were made in some datetime range (in Python) by making a dummy ObjectID.from_datetime() like so:

# gets docs which were created in last 5 minutes
resp = await collection.update_one({'_id': {'$gte': ObjectId.from_datetime(datetime.utcnow() - timedelta(minutes=5))}},
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文