How can one shorten mongo ids for better use in URLs?
I've built a number of python driven sites that utilize mongodb as a database backend and am very happy with it's ObjectId system, however, I'd love to be able encode the ids in a shorter fashion without building a mapping collection or utilizing a url-shortener service.
Suggestions? Success stories开发者_如何转开发?
You could compress them as Base62 numbers. This doesn't save a lot of space, but it does save you a few bytes per ID. My example's Ruby, but similar usage in Python wouldn't be hard.
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"
Heh, I recently wanted the exact same thing myself.
What I've ended up doing is giving every document that needs one a "public id" that is unique (like the ObjectId), but that is just an auto-incrementing number (so it'll take a while before the numbers get huge, and even longer if they're hex-encoded). This way, I can use the ObjectId internally (which I suspect is faster), and lookup externally referenced documents using their public id.
Note that there is a little performance hit when creating these public ids since each one requires an atomic update to a document (so you should only use them where you need them).
The key to creating an auto-incrementing number is MongoDB's findAndModify
command to both increment a value and return the old value in a single atomic operation.
Since you're using Python, and so am I, here is the code that I'm currently using (note that it's not in production yet):
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)
If you are attempting to retain the original value then there really is not a good way. You could encode it, but the likeliness of it being smaller is minimal. You could hash it, but then it's not reversible.
If this is a REQUIREMENT, I'd probably recommend creating a lookup table or collection where a small incremental number references entries in a Mongo Collection.
I brought this topic up a while ago on mongodb's mailing list. See if it can help you out.
Custom _id
If you can generate auto-incrementing unique numbers, there's absolutely no need to use ObjectId for _id. Doing this in a distributed environment will most likely be more expensive than using ObjectId. That's your tradeoff.
精彩评论