2017-08-06 4 views
1

次のデータストアモデルがあります。私は何をしたいのか、基本的にAppengineのKeyプロパティで接続されたエンティティに接続されているエンティティをすべて削除する方法

class UserDetail(ndb.Model): 
    name=ndb.StringProperty(required=True) 
    password=ndb.StringProperty(required=True) 
    email=ndb.StringProperty(required=False) 
    posts=ndb.KeyProperty(kind='Post',repeated=True) 

class Post(ndb.Model): 
    subject=ndb.StringProperty(required=True) 
    content=ndb.TextProperty(required=True) 
    created=ndb.DateTimeProperty(auto_now_add=True) 
    user=ndb.KeyProperty(kind='UserDetail') 
    comments=ndb.KeyProperty(kind='Comment',repeated=True) 

class Comment(ndb.Model): 
    body=ndb.StringProperty(required=True) 
    user=ndb.KeyProperty(kind='UserDetail') 
    post=ndb.KeyProperty(kind='Post') 

私は投稿を削除する場合、そのすべてのコメントが削除されますする必要があり、ポストも私は知っているUserDetail model.Theの道からユーザーのポストリストから削除されるはずですpost.Andを削除することです削除するには、投稿を削除し、指定された投稿IDでコメントモデルを検索し、それらのすべてを削除し、同じ方法でユーザの投稿リストに行き、必要な投稿を削除します。 これを行うにはより良い方法がありますか?

+2

サイドコメント: 'UserDetail'の' posts'プロパティと 'Post'の' comments'プロパティを削除します。スケーラビリティの問題です。追加/削除するたびにそれらのエンティティを書き直さなければなりません。それらのリスト内の要素を削除します。そして、これらのリストに追加/削除されなければならない要素の作成/削除のロジックが複雑になります。このリストをオンデマンドでクエリで得ることができます(最終的な一貫性のため実際にはこの使用例の問題です)。 –

+0

このモデルスキーマを作成したのは、私が使用していないという事実を補うためですリレーショナルデータベースつまり、ユーザーのプロフィールページを作成して、このスキーマを投稿したユーザー全員を表示したいのであれば、私はあなたが何を言っているかを簡単にどのように達成するのか分かりません。 –

答えて

2

pre_delete_hookを定義することをお勧めします。これは、エンティティが削除される前に実行される関数です。この機能を使用して、この投稿を参照するコメントを削除します。また、UserDetailsからキー値を削除することもできます。ユーザーべき

class Post(ndb.Model): 
    ... 
    @classmethod 
    def _pre_delete_hook(cls, key): 
     comments = Comment.query(Comment.post==key).fetch(keys_only=True) 
     ndb.delete_multi(comments) 

     details = UserDetail.query(UserDetail.posts.IN([key])).fetch() 
     for detail in details: 
      detail.posts.remove(key) 
     ndb.put_multi(details) 

理由はフックがあるので、あなたは関係なく実行されません欲しい機能がどのようなコードの一部Postを削除しようとしたことを保証する:コードは次のようになります。これは、リレーショナルデータベースを使用していないという事実を補う方法です。

フックの詳細については、documentationをご覧ください。私はそれが助けて欲しい!

+0

私は、これが実際に呼び出しコンテキストに関係なく機能するかどうかは完全にはわかりません。例えば、トランザクション内で '.delete()'が呼び出された場合、それがうまくいくかどうかは疑問です。非祖先クエリはトランザクション内では使用できません。また、最終的な一貫性のために、孤立したコメントの残り物のための余地が残されます。代わりに、私はちょうどより良い制御されたコンテキストで関連するエンティティの削除を実行するために遅延プッシュキュータスクをエンキューしたいと思います。 –

+0

こんにちは。はい、そうです。どのように( '.delete()'または 'ndb.delete_multi()')インスタンスを削除しても動作します。 以前は大規模なデータと一緒に使っていましたが、特にpre_put_hookを使用し、post_put_hookを使用しないと、結果的に一貫性の問題が発生することはありませんでした。 – Y2H

+0

ありがとう@ Y2H。しかし、私のプログラムでこのコードを適用すると、タイプ・エラーが発生し、キー・プロパティー・オブジェクトが反復可能ではないと言っています。私はこれがなぜ起こっているのか理解できません。コンソールでそれをチェックし、うまくいきました。 –

関連する問題