我是 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(在极少数情况下,两个 twitter 和 facebook 用户共享相同的 provider-id)
但是为了实现这一点,我需要设置两个索引,我认为这是不可能的。
那么我能做什么呢?我应该将两个字段连接为一个键和索引吗?
例如,新想法是:
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