私はndbとgaeが初めてで、インデックスを設定する良い解決策を考え出すのに問題があります。次のようなユーザー モデルがあるとします。
class User(ndb.Model):
name = ndb.StringProperty()
email = ndb.StringProperty(required = True)
fb_id = ndb.StringProperty()
ログイン時にクエリで電子メール アドレスを確認しようとすると、これは非常に遅く、非効率的であると思います。おそらく、完全なテーブル スキャンを実行する必要があります。
q = User.query(User.email == EMAIL)
user = q.fetch(1)
ユーザーモデルがメールをキーとして保存されていれば、はるかに高速になると思います。
user = user(id=EMAIL)
user.put()
そうすれば、このようにそれらをより速く取得できます(そう信じています)
key = ndb.Key('User', EMAIL)
user = key.get()
これまでのところ、私が間違っている場合は修正してください。しかし、これを実装した後、Facebook ユーザーがメールアドレスを変更する可能性があることに気付きました。新しい oauth2.0 接続時に、新しいメールがシステムで認識されず、新しいユーザーとして作成されます。したがって、おそらく別のアプローチを使用する必要があります。
- social-media-provider-id の使用 (すべてのプロバイダー ユーザーに固有)
と
- provider-name (まれに、2 人の Twitter ユーザーと Facebook ユーザーが同じプロバイダー ID を共有する場合があります)
ただし、これを実現するには、2 つのインデックスを設定する必要がありましたが、これは不可能だと思います。
それで、私は何ができるでしょうか?両方のフィールドを単一のキーとインデックスとして連結しますか?
たとえば、新しいアイデアは次のようになります。
class User(ndb.Model):
name = ndb.StringProperty()
email = ndb.StringProperty(required = True)
provider_id = ndb.StringProperty()
provider_type = ndb.StringProperty()
保存:
provider_id = 1234
provider_type = fb
user = user(id=provider_id + provider_type)
user.put()
検索:
provider_id = 1234
provider_type = fb
key = ndb.Key('User', provider_id + provider_type)
user = key.get()
これにより、ユーザーがソーシャル メディアでメール アドレスを変更しても、気にする必要がなくなります。この考えは正しいですか?
ありがとう、
アップデート
ティムのソリューションは、これまでのところ最もクリーンで、おそらく最速でもありました。しかし、私は問題に遭遇しました。
class AuthProvider(polymodel.PolyModel):
user_key = ndb.KeyProperty(kind=User)
active = ndb.BooleanProperty(default=True)
date_created = ndb.DateTimeProperty(auto_now_add=True)
@property
def user(self):
return self.user_key.get()
class FacebookLogin(AuthProvider):
pass
View.py: facebook_callback メソッド内
provider = ndb.Key('FacebookLogin', fb_id).get()
# Problem is right here. provider is always None. Only if I used the PolyModel like this:
# ndb.Key('AuthProvider', fb_id).get()
#But this defeats the whole purpose of having different sub classes as different providers.
#Maybe I am using the key handeling wrong?
if provider:
user = provider.user
else:
provider = FacebookLogin(id=fb_id)
if not user:
user = User()
user_key = user.put()
provider.user_key = user_key
provider.put()
return user