3

NDB を使用するようにコードをアップグレードした後にのみ現れた興味深い問題があります。

データベースに保存されている各セッションのキーにセッションの有効期限をエンコードするgae-sessionsを使用しています。たとえば、キーの形式は次のとおりです: 1363968220_6ea52c936f16fc557c0c03a5f276a056 ここで、最初の 10 文字はセッションの有効期限が切れたときのタイムスタンプを表します (値 1363968220 は「2013-03-22 16:03:40」をエンコードします)。

NDB にアップグレードする前は、期限切れのセッションを削除するコードが正しく機能していました。アップグレード後、コードは期限切れになっていないセッションを誤って削除します。コードは次のとおりです。

time_time = time.time()
now_str = unicode(int(time_time))
now_str_datetime = datetime.datetime.fromtimestamp(time_time) 
q = SessionModel.query(namespace='')
key = ndb.Key(SessionModel, now_str + u'\ufffd', namespace='')
logging.info("Deleting sessions with key values less than %s [%s]" % (key, now_str_datetime))
q.filter(SessionModel._key < key)
results = q.fetch(500, keys_only=True)
# This is for debugging purposes
for r_key in results:
    logging.warning("Deleting key %s" % (r_key))

これにより、次の出力が得られます。

Deleting sessions with key values less than Key('SessionModel', '1363362698\xef\xbf\xbd') [2013-03-15 15:51:38.767947]
Deleting key Key('SessionModel', '1363924467_e0240e38b4047ef821ac62e07466351b')

これらのキーが (文字列の順序付け/優先規則を使用して) 文字列として扱われる場合、削除されるキー (1363924467 で始まる) は、フィルタリング対象のキー (1363362698 で始まる) よりも小さいと見なされるべきではありません。これが正しく機能しない原因となる NDB で何が起こっているのか混乱しています。

4

1 に答える 1

2

説明するのは難しいですが、ドキュメントに基づいて

https://developers.google.com/appengine/docs/python/ndb/keyclass?hl=zh-tw

キーは、key1 == key2 または key1 < key2 などの比較をサポートします。これらの演算子は、アプリケーション ID、名前空間、および完全な「祖先パス」を比較します。キー プロパティまたはキーによる順序付けの際に、Datastore がクエリに使用するのと同じ順序付けを使用します。

チート シート https://docs.google.com/document/d/1AefylbadN456_Z7BZOpZEXDq8cR8LYu7QgI7bt5V0Iw/mobilebasic

そしてソースコード。すべてが使用法に問題がないことを示しています。キーは、app_id、namespace、およびキー ペアを順番に比較します。(key.app(), key.namespace(), key.pairs()) を印刷して詳細を確認してみてください。

https://code.google.com/p/appengine-ndb-experiment/source/browse/ndb/key.py

def __gt__(self, other):
    """Greater than ordering."""
    if not isinstance(other, Key):
      return NotImplemented
    return self.__tuple() > other.__tuple()

def __tuple(self):
    """Helper to return an orderable tuple."""
    return (self.app(), self.namespace(), self.pairs())
于 2013-03-16T03:29:52.697 に答える