Meteor使用其内部Random包为文档生成Mongo-Ids,其中used set of characters定义为:
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz";
Random.id
的{{3}}也指出:
返回唯一的标识符,例如
"Jjwjg6gouWLXhMGKW"
,在全球范围内很可能是唯一的。
,它是为ID的默认长度(17个字符; UNMISTAKABLE_CHARS
中的每个字符)定义的。
现在,我只想使用Id的前N个字符来缩短我的网址(其中包括Id,以动态加载需要特定文档(由Id确定)的页面)。
如果我的原始ID是
`v5sw59HEdX9KM5KQE`
我想举个例子(在这里考虑一个完全随机选择的N = 5):
{
_id:"v5sw59HEdX9KM5KQE",
short: "v5sw5"
}
作为文档架构,并使用{ short }
作为我的Mongo.Collection
中的查询通过此ID提取相应的文档。
现在我的问题是如果要考虑5000到10000之间的文档量(因此IDs),那么有多少个字符可以防止冲突。
注意:我前面有一些熵计算工具,所有这些值(字符集,原始ID的长度,文档数)都在我眼前,但我不知道如何接线所有这一切都可以安全地计算出N。
答案 0 :(得分:2)
至少在理论上,随机生成标识符已经冒了生成重复标识符的风险。对于默认的MongoID长度(假设其中有55 17 个),在生成了将近731156亿个随机MongoID之后,存在重复的MongoID的机会达到50%(请参阅“ Birthday problem”) ,因此在大多数情况下,实际上重复的机会微不足道。
缩短随机标识符将使碰撞问题更加严重。在这种情况下,对于5个字符的ID长度(导致55 5 或503284375个不同的ID),仅生成约26415个随机ID之后,重复的MongoID的机会达到50%。
由于似乎您无法像控制缩短的"unique IDs"一样容易地控制MongoID的生成方式,因此您可以做的一件事是:
但是请考虑您是否真的希望这种方式创建的短标识符是可预测的。使用短标识符几乎无法实现此可预测性目标。
如果您希望使用缩短的MongoID,请参阅“ Birthday problem”,了解可用来估计允许随机数发生碰撞的随机数的公式。
有关Meteor如何生成MongoID的更多信息,另请参见this question;它的答案之一包括一种让MongoDB在服务器上生成MongoID而不是让Meteor在客户端上生成MongoID的方法。同样,Meteor似乎在将它们生成的MongoID插入文档之前也不会对其进行唯一性检查。
答案 1 :(得分:2)
如果我的理解正确,除了为您的文档_id生成正常的17个字符长的id之外,您还希望使用较短的ID,这样通常在包含该ID的情况下,URL看起来就不会那么吓人了。
在您的示例中,您截断了ID,因此在较短的ID与原始文档ID之间建立了显式关联。
这听起来像git short commit hash:How does Git(Hub) handle possible collisions from short SHAs?
您可以遵循类似的路径,即首先确定合理的初始默认长度,以避免可能的冲突(如Peter O.的回答中所述),但显式检查服务器端的唯一性并增加任何长度新的缩短版本,以防发生冲突,直到再次变得唯一。
答案 2 :(得分:2)
我认为,如果要避免在小集合上发生冲突,那么不要要使用随机ID,但是要么使用完全确定性ID,要么至少将随机性降低到某种程度更有控制力。按照这些原则,您可以考虑的另一种选择是使用MONGO
for idGeneration
in your collection。这些ID是在known recipe之后生成的。因此,您可以使用该ID的1-4和12个字符,并且只要在同一秒内创建的文档数不超过N个,就可以保证没有哈希冲突,其中N是MongoID中使用的字符数(即不知道一手掌握)。