1

mapreduce を使用して GAE のデータストアでスキーマのアップグレードを実行するための基盤のセットアップが完了しました。NDB を使用しており、モデルの多くまたはモデルは、DateTimeProperty の auto_now キーワード オプションを使用して、last_modified 属性を設定します。

last_modified = ndb.DateTimeProperty( auto_now=True )

もちろん、エンティティを更新する mapreduce ジョブを実行すると、last_modified 属性も更新されますが、これは実際には望んでいないことです。

def upgrade_entity(entity):
    # modify entity
    yield op.db.Put(entity)

ドキュメントによると、auto_now_add を設定してプロパティの値をオーバーライドできますが、auto_now ではオーバーライドできません。

last_modified 属性も更新したくない状況が他にもあるのではないかと考えています。

それで、エンティティの last_modified 値を保持する方法はありますか、それとも別のプロパティを追加するか、これらのプロパティを制御できるものに置き換えて、値を手動で設定するだけですか?


わかりましたので、コンセンサスは、ユーザー向けのコードではなく、mapreduce コードでのみ使用されるモデルの代替バージョンを定義できるはずだということです (サイトをシャットダウンして実行する必要は避けたいと思っています)。スキーマのアップグレード) しかし、これを機能させることができませんでした。

次のセットアップでは、適切に動作する (last_modified を更新しない) mapreduce を実行するまで、ユーザー向けのコードは適切に動作します (last_modifed を更新します)。mapreduce を実行した後、ユーザー向けコードは last_modified を更新しなくなりました。

models.py

class MyModel(ndb.Model):
    # model used by user facing code
    last_modified = ndb.DateTimeProperty( auto_now=True )

upgrade.py

class MyTmpModel(ndb.Model):
    # model used by mapreduce code
    @classmethod
    def _get_kind(cls):
        return 'MyModel'
    last_modified = ndb.DateTimeProperty( auto_now=False )

def upgrade_model(entity):
    # mapper function 
    # modify entity
    yield op.db.Put(entity)     

mapreduce.yaml

mapreduce:
- name: Upgrade Model
  mapper:
    input_reader: mapreduce.input_readers.DatastoreInputReader
    handler: upgrade.upgrade_model
    params:
    - name: entity_kind
      default: upgrade.MyTmpModel


わかりました、ここで私の問題を dev_server でテストしたという事実と、実際の gae サーバーと比較してそこで実行される方法の違いを説明します。私は、dev_server ではすべてのコードが同じプロセスで実行されており、異なるモデル バージョンがうまく機能していないと結論付けました。NDB モデル ドキュメントから:

アプリケーションは、異なるモジュールに存在する場合でも、同じ種類の 2 つのモデル クラスを定義するべきではありません。アプリケーションの種類は、グローバルな「名前空間」と見なされます。

実際のgaeサーバーではmapreduceコードが別々のインスタンスで実行され、これらのバージョンの衝突は発生せず、サーバーインスタンスに直面しているユーザーには影響しないため、上記のセットアップは期待どおりに機能するという事実に頼ることができると仮定します. .

助けてくれたティムとグイドに感謝します。

乾杯、

J

4

1 に答える 1

1

解決策は、map/reduce コードのすべてのモデル定義で auto_now=False を設定することです。

エラーの可能性を最小限に抑えてこれを行うための私の提案:

モデル定義のすべての auto_now 設定に使用する、True または False のグローバル定数を定義します。次に、その 1 行だけを変更して、すべてのモデルで True から False に変更する必要があります。環境変数に基づいて値を自動的に計算させることもできます。

于 2012-08-01T17:26:33.640 に答える