4

オリジナルデザイン

これが私が最初にModelsセットアップした方法です:

class UserData(db.Model):
    user = db.UserProperty()
    favorites = db.ListProperty(db.Key) # list of story keys
    # ...

class Story(db.Model):
    title = db.StringProperty()
    # ...

ストーリーを表示するすべてのページで、現在のユーザーの UserData をクエリします。

user_data = UserData.all().filter('user =' users.get_current_user()).get()
story_is_favorited = (story in user_data.favorites)

新しいデザイン

Google I/O 2009 - Scalable, Complex Apps on App Engineの講演を見た後、もっと効率的にセットアップできないかと考えました。

class FavoriteIndex(db.Model):
    favorited_by = db.StringListProperty()

Story Model同じですが、 を削除しましたUserData Model。new の各インスタンスには、親としてインスタンスFavoriteIndex Modelがあります。Storyそして、それぞれがそのプロパティFavoriteIndexにユーザー ID のリストを格納しfavorited_byます。

特定のユーザーがお気に入りにしたすべてのストーリーを検索したい場合:

index_keys = FavoriteIndex.all(keys_only=True).filter('favorited_by =', users.get_current_user().user_id())
story_keys = [k.parent() for k in index_keys]
stories = db.get(story_keys)

このアプローチは、ListProperty に関連付けられているシリアル化/逆シリアル化を回避します。

効率とシンプルさ

特にユーザーが 300 のストーリーをお気に入りに登録した後では、新しいデザインがどれほど効率的かはわかりませんが、私が気に入っている理由は次のとおりです。

  1. お気に入りのストーリーは、ユーザーではなくユーザーに関連付けられていますuser data

  2. を表示するページでは、お気に入りに追加されstoryているかどうかを簡単にstory確認できます (ユーザー データで満たされた別のエンティティを呼び出す必要はありません)。

    fav_index = FavoriteIndex.all().ancestor(story).get()
    fav_of_current_user = users.get_current_user().user_id() in fav_index.favorited_by
    
  3. ストーリーをお気に入りにしたすべてのユーザーのリストを取得するのも簡単です (#2 の方法を使用)。

もっと簡単な方法はありますか?

助けてください。この種のことは通常どのように行われますか?

4

4 に答える 4

2

あなたが説明したことは良い解決策です。ただし、さらに最適化することもできます。お気に入りごとに、関連する Story エントリの子エンティティとして (または同等に、UserInfo エントリの子エンティティとして) 'UserFavorite' エンティティを作成し、キー名をユーザーの一意の名前に設定します。 ID。このようにして、単純な get でユーザーがストーリーをお気に入りに追加したかどうかを判断できます。

UserFavorite.get_by_name(user_id, parent=a_story)

get 操作はクエリよりも 3 ~ 5 倍高速であるため、これは大幅な改善です。

于 2009-10-13T20:04:12.340 に答える
1

私はあなたの実際の質問に取り組みたくありませんが、ここに非常に小さなヒントがあります:あなたはこのコードを置き換えることができます:

if story in user_data.favorites:
    story_is_favorited = True
else:
    story_is_favorited = False

この一行で:

story_is_favorited = (story in user_data.favorites)

必要がなければ、括弧を付ける必要はありstory in user_data.favoritesません。私はそれがより読みやすいと思います。

于 2009-10-13T19:20:41.927 に答える
1

2つのモデルの結合のようにお気に入りのインデックスを作成できます

class FavoriteIndex(db.Model):
    user = db.UserProperty()
    story = db.ReferenceProperty()

また

class FavoriteIndex(db.Model):
    user = db.UserProperty()
    story = db.StringListProperty()

次に、ユーザーによるクエリは、ユーザーがお気に入りに追加したストーリーごとに1つのFavoriteIndexオブジェクトを返します。

ストーリーごとにクエリを実行して、お気に入りに追加したユーザーの数を確認することもできます。

小さいサイズに制限されていることがわかっていない限り、何もスキャンしたくない

于 2009-10-13T20:08:28.290 に答える
1

新しいデザインを使用すると、ユーザーが特定のストーリーをクエリでお気に入りに登録したかどうかを調べることができます。
UserFavorite クラス エンティティは必要ありません。
これは keys_only クエリであるため、get(key) ほど高速ではありませんが、通常のクエリよりも高速です。
FavoriteIndex クラスはすべて同じ key_name='favs' を持ちます。
__key__ に基づいてフィルタリングできます。

a_story = ......
a_user_id  = users.get_current_user().user_id()
favIndexKey = db.Key.from_path('Story', a_story.key.id_or_name(), 'FavoriteIndex', 'favs')
doesFavStory = FavoriteIndex.all(keys_only=True).filter('__key__ =', favIndexKey).filter('favorited_by =', a_user_id).get()

複数の FavoriteIndex を Story の子として使用する場合は、祖先フィルターを使用できます

doesFavStory = FavoriteIndex.all(keys_only=True).ancestor(a_story).filter('favorited_by =', a_user_id).get()
于 2009-10-19T15:27:48.780 に答える