Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 重复Mongo ObjectId的可能性';是在两个不同的集合中生成的吗?_Mongodb_Database_Nosql - Fatal编程技术网

Mongodb 重复Mongo ObjectId的可能性';是在两个不同的集合中生成的吗?

Mongodb 重复Mongo ObjectId的可能性';是在两个不同的集合中生成的吗?,mongodb,database,nosql,Mongodb,Database,Nosql,是否可能为两个不同集合中的文档生成相同的Mongo ObjectId?我意识到这绝对是不可能的,但有可能吗 我问的原因不是太具体,而是通过我正在开发的一个应用程序,我们展示了当选官员的公开资料,我们希望这些人能成为我们网站的正式用户。我们为目前不是我们网站成员的用户和当选官员提供了单独的收藏。还有其他各种文件,其中包含有关当选官员的各种数据,所有这些数据都映射回使用当选官员ObjectId的人 创建帐户后,我们仍然会突出显示与当选官员相关的数据,但这些数据现在也是用户集合的一部分,并带有相应的u

是否可能为两个不同集合中的文档生成相同的Mongo ObjectId?我意识到这绝对是不可能的,但有可能吗

我问的原因不是太具体,而是通过我正在开发的一个应用程序,我们展示了当选官员的公开资料,我们希望这些人能成为我们网站的正式用户。我们为目前不是我们网站成员的用户和当选官员提供了单独的收藏。还有其他各种文件,其中包含有关当选官员的各种数据,所有这些数据都映射回使用当选官员ObjectId的人

创建帐户后,我们仍然会突出显示与当选官员相关的数据,但这些数据现在也是用户集合的一部分,并带有相应的users ObjectId,以将其配置文件映射到与我们的应用程序的交互

几个月前,我们开始将应用程序从MySql转换为Mongo,在转换过程中,我们存储这两种数据类型的传统MySql id,现在我们也开始在用户文档中存储选定的官方Mongo ObjectId,以映射回选定的官方数据

我正在考虑将新用户ObjectId指定为以前选择的官方ObjectId,以使事情更简单,但希望确保不可能与任何现有用户ObjectId发生冲突

谢谢你的洞察力


编辑:发布这个问题后不久,我意识到我提出的解决方案不是一个好主意。最好只保留我们现有的模式,并在用户文档中链接到选定的官方“\u id”。

对于集合中的ObjectId唯一性没有任何保证。即使可能性很小,但这将是一个非常糟糕的应用程序设计,它依赖于跨集合的_id唯一性

可以在mongo shell中轻松测试这一点:

MongoDB shell version: 1.6.5
connecting to: test
> db.foo.insert({_id: 'abc'})
> db.bar.insert({_id: 'abc'})
> db.foo.find({_id: 'abc'})
{ "_id" : "abc" }
> db.bar.find({_id: 'abc'})
{ "_id" : "abc" }
> db.foo.insert({_id: 'abc', data:'xyz'})
E11000 duplicate key error index: test.foo.$_id_  dup key: { : "abc" }
所以,绝对不要依赖于_id在集合中是唯一的,因为您不控制ObjectId生成函数,所以不要依赖它

可以创建更像uuid的东西,如果手动创建,可以更好地保证唯一性


请记住,您可以将不同“类型”的对象放在同一集合中,那么为什么不将两个“表”放在同一集合中呢。它们将共享相同的id空间,因此保证是唯一的。从“预期”切换到“注册”只需简单地翻转一个字段…

ObjectID是以类似于UUID的方式在客户端生成的,但在数据库中具有一些更好的存储属性,例如大致增加顺序并免费编码其创建时间。对于您的用例来说,关键的一点是,即使它们是在不同的机器上生成的,它们的设计也能保证高概率的唯一性

现在,如果您通常引用_id字段,我们不需要跨集合的唯一性,因此可以安全地重用旧的_id。作为一个具体的示例,如果您有两个集合,
colors
fruits
,则这两个集合都可以同时具有类似
{u id:'orange'}
的对象


如果您想了解更多有关如何创建ObjectID的信息,请参阅规范:

简短回答

仅对您的初始问题添加一个直接的回答:是的,如果您使用BSON对象ID生成,那么对于大多数驱动程序来说,ID几乎肯定会在集合中是唯一的。“几乎肯定”的含义见下文

长答案

Mongo DB驱动程序生成的BSON对象ID在集合中很可能是唯一的。这主要是因为ID的最后3个字节,对于大多数驱动程序,它是通过静态递增计数器生成的。该计数器是独立于收集的;这是全球性的。例如,Java驱动程序使用随机初始化的静态AtomicInteger

那么,为什么在Mongo文档中,他们说ID“很可能”是唯一的,而不是直接说它们是唯一的呢?在您无法获得唯一ID的情况下,可能会出现三种情况(如果有更多,请告诉我):

在此讨论之前,请记住BSON对象ID包括:

[4字节自历元起秒,3字节机器哈希,2字节进程ID,3字节计数器]

以下是三种可能性,因此您可以自己判断被骗的可能性:

1) 计数器溢出:计数器中有3个字节。如果在同一台计算机上、同一进程中,在一秒钟内插入了超过16777216(2^24)个文档,则可能会使递增计数器字节溢出,并最终导致两个对象ID共享相同的时间、计算机、进程和计数器值

2) 计数器非递增:一些Mongo驱动程序对计数器字节使用随机数而不是递增数。在这些情况下,有1/16777216的机会生成非唯一ID,但前提是这两个ID是在同一秒(即,在ID的时间段更新到下一秒之前)在同一台机器上以相同的过程生成的

3) 将计算机和进程哈希设置为相同的值。在某些极不可能的情况下,机器ID和进程ID值可能映射到两台不同机器的相同值。如果发生这种情况,并且两台不同机器上的两个计数器同时在同一秒钟内生成相同的值,那么您将得到一个重复的ID

这是需要注意的三种情况。场景1和场景3看起来不太可能,如果使用正确的驱动程序,场景2是完全可以避免的。您必须检查驱动程序的来源才能确定

万一有人