_id上的mongodb排序顺序


72

我不知道mongodb在执行如下查询时如何比较“ _id”字段:

db.data.find({"_id":{$gt:ObjectId("502aa46c0674d23e3cee6152")}}).sort({"_id":1}).limit(10);

它是纯粹基于id的时间戳部分吗?

Answers:


58

稍微扩展一下Andre所说的话:

由于ObjectID时间戳仅为第二个,因此可以轻松地创建两个(或多个)具有相同时间戳值(前4个字节)的ObjectID。如果这些是在同一台机器(机器ID-接下来的3个字节)上通过相同的进程(PID-接下来的2个字节)创建的,则唯一区分它们的就是“ inc”字段,最后3个字节在最后。

更新:2020年1月

这个答案仍然很受欢迎,因此值得进行一些更新。自从8年前写了这个答案以来,ObjectID规范已经得到了发展,现在时间戳之后的5个字节现在只是随机的,这将大大降低发生冲突的可能性。最后三个字节仍是递增的,但初始化为随机值以开始,从而再次降低了冲突的可能性。现在,ObjectID包含的上下文较少(您无法轻易分辨出它是在哪里生成的以及由哪个进程生成的),但是我猜想该信息并未以任何有意义的方式被使用,并且已被弃用,以便更好地对ID进行随机化。

结束更新

完整的规格请看这里:

https://docs.mongodb.com/manual/reference/method/ObjectId/#ObjectIDs-BSONObjectIDSpecification

假定规范正确实现,那么“ inc”字段要么是一个不断增加的字段(那么您可以合理地期望排序按插入/创建顺序),要么是一个随机值(那么可能是唯一的,但没有排序)。 。请注意,ObjectID可能是由驱动程序或应用程序生成的(或者实际上是手动生成的),而不是由MongoDB本身生成的,因此,除非您完全控制它们的生成方式,否则上述任何一项或全部均可适用。


3
由于它是由应用程序生成的,从技术上讲(此处为纯净者),它永远不会按插入进行排序,而是在驱动程序将_id应用到文档时进行排序。
Sammaye,2012年

3
由于我们注意到了技术细节,因此_id是由应用程序生成的(如果它是由应用程序生成的,或者由驱动程序(或您)在客户端指定它)。如果插入时没有将_id作为文档的一部分传递,则_id由服务器生成,因此驱动程序将其应用于文档时并不总是如此。
亚当·科默福德

1
当我们必须在mongodb中对该列进行排序时,哪个更好ObjectId还是auto increment主键?
罗希特·哈特里

ObjectId是默认值,并且在代码库中对其进行了一些优化。我还没有测试,但是我期望差异会很小,但是如果我进行有根据的猜测,我会在自动递增字段上使用ObjectId
Adam Comerford

我不知道谁或是否有人需要知道这一点,mongodb中的find()不能保证返回的文档与插入的文档顺序相同。或按_id排序如果需要,您需要明确指定排序。
Yogesh

30

以某种方式您是正确的,如果按排序,_id则将按插入时间排序。这并不意味着唯一的比较是在时间戳部分进行的。ObjectID本身就是BSON对象类型,可以直接相互比较。从时间戳开始,从逻辑上讲,过去的时间将少于将来的时间。

您可以在文档中找到更多详细信息


15

从Mongo规格复制粘贴 https://docs.mongodb.com/manual/reference/bson-types/#objectid

ObjectId值的顺序与生成时间之间的关系在一秒钟内并不严格。如果多个系统或单个系统上的多个进程或线程在一秒内生成值;ObjectId值不代表严格的插入顺序。客户端之间的时钟偏差也可能导致非严格排序,即使对于值也是如此,因为客户端驱动程序生成ObjectId值,而不是mongod进程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.