web-dev-qa-db-ja.com

UUIDの32文字の16進文字列を「YouTubeスタイル」の短いIDに変換して戻します。

すべてのMongoDBドキュメントにGUID using uuid.uuid1()を割り当てています。次のように、11文字の一意で大文字と小文字を区別するYouTubeのようなIDを取得する方法が必要です

1_XmY09uRJ4 

次のようなuuidの結果の16進数文字列から

ae0a0c98-f1e5-11e1-9t2b-1231381dac60

データベースに別の文字列を格納しなくても、短縮されたIDを16進数と動的に照合したり、その逆を動的に行うことができます。誰かがいくつかのサンプルコードを持っているか、これを行うことができるモジュールまたは式の方向に私を向けることができますか?

28
zakdances

基になるバイトをbase64値に変換し、_=_パディングと改行を削除します。

_/_と_+_(___と_-_が代わりに使用されます)を避けるために、おそらく base64.urlsafe_b64encode() function を使用する必要があります)、結果の文字列はURLパス要素として使用できます。

_>>> import uuid, base64
>>> base64.urlsafe_b64encode(uuid.uuid1().bytes).rstrip(b'=').decode('ascii')
'81CMD_bOEeGbPwAjMtYnhg'
_

逆:

_>>> uuid.UUID(bytes=base64.urlsafe_b64decode('81CMD_bOEeGbPwAjMtYnhg' + '=='))
UUID('f3508c0f-f6ce-11e1-9b3f-002332d62786')
_

それをジェネリック関数に変えるには:

_from base64 import urlsafe_b64decode, urlsafe_b64encode
from uuid import UUID

def uuid2slug(uuidstring):
    return urlsafe_b64encode(UUID(uuidstring).bytes).rstrip(b'=').decode('ascii')

def slug2uuid(slug):
    return str(uuid.UUID(bytes=urlsafe_b64decode(slug + '==')))
_

これにより、16バイトのUUIDをよりコンパクトな形式で表すことができます。さらに圧縮すると情報が失われます。つまり、完全なUUIDに再度圧縮解除することはできません。 16バイトで表現できる値の範囲全体は、22 base64文字未満には決して適合しません。入力の3バイトごとに4文字が必要であり、すべての文字が6ビットの情報をエンコードします。

したがって、YouTubeの一意の文字列は完全な16バイトのUUIDに基づいていないため、それらの11文字のIDは、簡単に検索できるようにデータベースに格納され、より小さな値に基づいています。

50
Martijn Pieters

あなたはPythonのbase64モデル。 A GUIDは基本的に数値の16進数表現であり、ハイフンを削除して、16進数からデコードし、64進数にエンコードすることができます。逆に進むには、64進数からのデコードが必要です。ベース16でエンコードし、適切な場所にハイフンを挿入します。

1
Platinum Azure

URLセーフな方法でuuidを短縮する方法を特に探している人にとって、 @ MartijnPieters からの本当に有用な回答は base64@ okoboko からの回答に関するコメントと同様に、URLセーフではない文字を処理するモジュール(いくつかの不要なビットなし)。

import base64
import uuid

# uuid to b64 string and back
uuid_to_b64str = base64.urlsafe_b64encode(uuid.uuid1().bytes).decode('utf8').rstrip('=\n')
b64str_to_uuid = uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuid_to_b64str}=='))

# uuid string to b64 string and back
uuidstr_to_b64str = base64.urlsafe_b64encode(uuid.UUID(str(uuid.uuid1())).bytes).decode('utf8').rstrip('=\n')
b64str_to_uuidstr = str(uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuidstr_to_b64str}==')))
0
benvc