3

App Engineデータストアを使用していて、行IDがmySQL DBの「自動インクリメント」フィールドと同様に動作するようにしたいと考えています。App Engineデータストア内の自動インクリメントID

は、いくつかの世代の戦略を試してみましたが、何が起こるかを制御を取るように見えることはできません:IDが連続していない

  • 、並行して成長しているいくつかの「ストリーム」があるように思われます。
  • 古い行が

を削除された後、IDが「リサイクル」を取得は、すべての可能性のようなものですか? 私は実際には、各行のタイムスタンプを保持することを控えています。

+2

あなたはニック・ジョンソンの[答え]をチェックすることもできます(http://stackoverflow.com/questions/3985812/how-to-implement google-appengine-on-google-appengine)を使用します。 –

+0

http:// stackoverflowを参照してください。com/questions/3985812/how-to-implement-autoincrement-on-google-appengine – max

+1

数字が単調増加して増加する必要があるのはなぜですか? –

答えて

1

私が知っているのは、自動生成されたIDはGoogle App Engineで利用できる長整数型であるということですが、値が増加しているという保証はなく、数字が実際の1インクリメントであるという保証もありません。

タイムスタンプと増分がない場合は、ミリ秒単位のDateTimeフィールドを追加しますが、数値が一意でないことはわかりません。 (そのため申し訳ありませんが、これは私見確かに最適なオプションです)

  • は、我々は客観化を使用(ロングとして自動生成されたIDを使用しますので、

    、これは(私たちは何を使っている)行うことが最善でありますJavaの)

  • は、私はしかし、ことに注意して、これはおそらくかなり良い解決策だと思う各エンティティのタイムスタンプを使用してトップX
0

を取得するために(降順索引を使用)エンティティを照会するためにインデックスを使用します私はをテストしていないそれinどのような形、形または形であってもよい。構文が正しくない場合もあります。

原則は、memcacheが失敗した場合にデータストアを使用してフォールバックを提供するためにmemcacheを使用して単調なシーケンスを生成することです。

class IndexEndPoint(db.Model): 
    index = db.IntegerProperty (indexed = False, default = 0) 

def find_next_index (cls): 
    """ finds the next free index for an entity type """ 
    name = 'seqindex-%s' % (cls.kind()) 

    def _from_ds(): 
     """A very naive way to find the next free key. 

     We just take the last known end point and loop untill its free. 
     """ 

     tmp_index = IndexEndPoint.get_or_insert (name).index 

     index = None 
     while index is None: 
      key = db.key.from_path (cls.kind(), tmp_index)) 
      free = db.get(key) is None 
      if free: 
       index = tmp_index 
      tmp_index += 1 

     return index 

    index = None 

    while index is None: 
     index = memcache.incr (index_name) 
     if index is None: # Our index might have been evicted 
      index = _from_ds() 
      if memcache.add (index_name, index): # if false someone beat us to it 
       index = None 

    # ToDo: 
    # Use a named task to update IndexEndPoint so if the memcache index gets evicted 
    # we don't have too many items to cycle over to find the end point again. 

    return index 


def make_new (cls): 
    """ Makes a new entity with an incrementing ID """ 

    result = None 

    while result is None: 
     index = find_next_index (cls) 


     def txn(): 
      """Makes a new entity if index is free. 

      This should only fail if we had a memcache miss 
      (does not have to be on this instance). 
      """ 
      key = db.key.from_path (cls.kind(), index) 
      if db.get (key) is not None: 
       return 

      result = cls (key) 
      result.put() 
      return result 

     result = db.run_in_transaction (txn) 
1

あなたはcan't rely on IDs being sequentialのように聞こえるかもしれません。しかし、あなたがやろうとしているものを達成するための簡単な方法があります:

我々は( 例えば2ヶ月の価値よりも古い、)古いアイテムを削除したい

はここでaはそのモデルの作成時間と変更時間を自動的に追跡します。単にauto_now_addauto_nowのパラメータを使用するだけで、これは簡単です。

from google.appengine.ext import db 

class Document(db.Model): 
    user = db.UserProperty(required=True) 
    title = db.StringProperty(default="Untitled") 
    content = db.TextProperty(default=DEFAULT_DOC) 
    created = db.DateTimeProperty(auto_now_add=True) 
    modified = db.DateTimeProperty(auto_now=True) 

その後は、古いものを削除するメンテナンスタスクをスケジュールするcron jobsまたはtask queueを使用することができます。最も古いものは作成日または変更日でソートするのと同じくらい簡単です検索:

db.Query(Document).order("modified") 
# or 
db.Query(Document).order("created") 
+0

ご返信ありがとうございます。可能であれば、私はこの質問で言及したように、インデックス付きのタイムスタンプ列を保持しないようにしたいと思います。私は、この目的のために行IDを「乱用する」というトリックを探していました。 – user1053539