#daiizメモ

Scrapboxに夢中

【GAE/Python】Google App EngineのデータストアでのURLセーフキー, id, エンティティの種類

Google App Engine のデータストア(Cloud Datastore)に保存されるアイテム(エンティティ)には,「エンティティの種類」と「id」が与えられている.

例えば,ユーザー情報を管理するデータモデルを

from google.appengine.ext import db

class User (db.Model): 
    first_name = db.StringProperty()
    last_name  = db.StringProperty()
    user_name  = db.StringProperty()

のように定義して,これのインスタンスをデータストアに保存した場合には「エンティティの種類」はUserとなる.idは保存時に自動で採番される.

エンティティの種類, idを取得する方法

プログラム中でエンティティeの情報を取得したい場合は,関数keyを使えばよい.先のものとは別の例での実行結果は以下のとおり.

print(e.key())
# -> datastore_types.Key.from_path(u'Screenshot', 5348024557502464L, _app=u'dev~svgscreenshot')

print("%s" % str(s.key().id()))  # エンティティのid
# -> 5348024557502464

print("%s" % s.key().kind())  # エンティティの種類
# -> Screenshot

エンティティの種類やidを取得できると,エンティティ固有内容をシェアするウェブページのURLを構成する場合に役立つ.

f:id:daiiz:20160827035845p:plain:h70

URLセーフキー

上記例での e.key() で得られた結果を文字列化すると,以下のように,

print("%s" % str(e.key()))
# -> ahFkZXZ-c3Znc2NyZWVuc2hvdHIXCxIKU2NyZWVuc2hvdBiAgICAgIDACQw

少々長めのキーが得られる.これは何か?
Google Cloud Consoleの「データストア」の項目での説明によると,上記で得られた文字列は「URL セーフキー」と呼ばれるものらしく,下記引用のような説明が書かれていた.

これはエンティティの種類と ID を base64 でエンコードした、シリアライズ バージョンです。 Cloud Console、App Engine クライアント ライブラリ、Cloud Datastore NDB クライアント ライブラリの URL セーフキーを使用できます。 警告: URL セーフキーは暗号化されていません。種類や ID に機密データが含まれている場合、URL セーフキーから簡単に解読できるので注意してください。

これを読む限りだと,URLセーフキーを解読(base64デコード)すれば「エンティティの種類」と「id」を取得することができるようなので,挑戦してみる.

url_safe_key = 'ahFkZXZ-c3Znc2NyZWVuc2hvdHIXCxIKU2NyZWVuc2hvdBiAgICAgIDACQw'
decoded_key  = base64.urlsafe_b64decode(url_safe_key + ('=' * (4 - len(url_safe_key) % 4)))
# -> 'j\x11dev~svgscreenshotr\x17\x0b\x12\nScreenshot\x18\x80\x80\x80\x80\x80\x80\xc0\t\x0c'

16進表記と制御文字の変換は,http://www.oocities.org/dtmcbride/tech/charsets/ascii.html を眺めるとわかる.

  • \x11: ^Q (Default UNIX START char)
  • dev~svgscreenshot: アプリ名(svgscreenshotのローカル開発環境)
  • \x17: ^W (End of transmission block)
  • \x0b\x12 ^K (Vertical tab) ^R
  • \n: 改行
  • Screenshot: エンティティの種類
  • \x18: ^X (Cancel)
  • \x80\x80\x80\x80\x80\x80\xc0: おそらくidを表している?(正解id = 5348024557502464 = 128 ^ 6 + 1216.128は \x80 の10進表記で,6は\x80の出現回数?.1216の出処が不明.\xc0未使用)
  • \t: タブ
  • \x0c: ^L (Form feed)

エンティティidがわからない...
このあたりの解読方法について,上手くいきそうな手法をご存知の方がいれば教えてください!!