2010-11-23 44 views
13

我已经构建了一些利用MongoDB作为数据库后端的python驱动的站点,并且非常满意它的ObjectId系统,但是,我希望能够以更短的方式编码id,而无需构建映射集合或利用网址缩短服务。如何缩短mongo ID以便在URL中更好地使用?

对此提出建议?成功的故事?

回答

7

嘿,我最近想要自己完全一样的东西。

我最终做的是给每一个需要一个“公共ID”的唯一的文档(如ObjectId),但这只是一个自动递增的数字(所以它需要一段时间数字变得巨大,如果它们是十六进制编码的话,甚至更长)。这样,我可以在内部使用ObjectId(我怀疑它更快),并使用它们的公共ID查找外部引用的文档。

请注意,创建这些公共标识符时会有一些性能问题,因为每个标识符都需要对文档进行原子更新(因此您只应在需要它们的地方使用它们)。

创建自动递增数字的关键是MongoDB的findAndModify command增加一个值并返回一个原子操作中的旧值。

由于您使用Python的,而且我也相信,这里是我目前使用的(请注意,这不是在生产中还)代码:

from pymongo import Connection 
from pymongo.son import SON 

db = Connection().mydatabase 

PUBLIC_ID_COLLECTION = 'next_public_id' 
def next_public_id(): 
    result = db.command(SON({ 'findandmodify': PUBLIC_ID_COLLECTION }, 
     query = { '_id': 'manager' }, 
     update = { '$inc': { 'next_public_id': 1 } }, 
     upsert = True  # Insert if not already existing 
    )) 
    manager = result['value'] 
    return manager.get('next_public_id', 0) 
12

你可以压缩它们为Base62数字。这不会节省很多空间,但它确实为您节省了每个ID几个字节。我的例子的Ruby,但在Python中的类似用法并不难。

ree-1.8.7-2010.02 > User.first._id.to_s 
=> "4c76f3dd98db74697500003b" 

ree-1.8.7-2010.02 > User.first._id.to_s.to_i(16).base62_encode 
=> "uMarF7LmpY3bNOSn" 
+0

你如何解码?另外,在查找资源时,是否更快解码,然后通过_id查找,或者只是向base62编码字段添加索引? – user1071182 2013-03-13 11:39:14

1

如果您试图保留原始值,那么确实不是一个好方法。你可以编码它,但它的可能性很小。你可以散列它,但那不是可逆的。

如果这是一个需求,我可能会建议创建一个查询表或集合,其中一个小增量数引用Mongo Collection中的条目。

1

我在mongodb的邮件列表上刚刚提到了这个话题。看看它是否可以帮助你。

Custom _id

0

如果您可以生成自动递增的唯一的号码,但绝对没有必要使用的ObjectId为_id。在分布式环境中执行此操作很可能比使用ObjectId更昂贵。这是你的权衡。