gpt4 book ai didi

google-app-engine - 是否可以将两个字段设置为ndb中实体的索引?

转载 作者:行者123 更新时间:2023-12-03 03:53:26 26 4
gpt4 key购买 nike

我是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)

我相信,如果使用电子邮件作为 key 保存用户模型,速度会快得多。

user = user(id=EMAIL)
user.put()

这样我就可以更快地检索它们(所以我相信)

key = ndb.Key('User', EMAIL) 
user = key.get()

到目前为止,如果我错了,请纠正我。但在实现这个之后,我意识到 Facebook 用户有可能更改他们的电子邮件地址,这样在新的 oauth2.0 连接上,他们的新电子邮件无法在系统中识别,并且他们将被创建为新用户。因此也许我应该使用不同的方法:

  • 使用社交媒体提供商 ID(对于所有提供商用户而言都是唯一的)

  • 提供商名称(在极少数情况下,两个 Twitter 和 Facebook 用户共享相同的提供商 ID)

但是为了实现这一点,我需要设置两个索引,我认为这不是 possible .

那我能做什么呢?我应该将这两个字段连接为单个键和索引吗?

例如新想法是:

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

最佳答案

您的方法的一个细微变化是为provider_id、provider_type创建一个单独的实体,作为 key 或您提出的任何其他身份验证方案,这可以允许更灵活的模型

该实体随后保存实际用户详细信息的引用(键)。

然后你就可以

  1. 直接 get() 获取身份验证详细信息,然后 get() 实际用户详细信息。
  2. 可以更改身份验证详细信息,而无需实际重写/重新输入用户详细信息
  3. 您可以为单个用户支持多个身份验证方案。

我将这种方法用于拥有超过 2000 个用户的应用程序,大多数用户使用自定义身份验证方案(应用程序特定的用户 ID/密码)或 Google 帐户。

例如

class AuthLogin(ndb.Polymodel):
user_key = ndb.KeyProperty(kind=User)
status = ndb.StringProperty() # maybe you need to disable a particular login with out deleting it.
date_created = ndb.DatetimeProperty(auto_now_add=True)

@property
def user(self):
return self.user_key.get()


class FacebookLogin(AuthLogin):
# some additional facebook properties

class TwitterLogin(AuthLogin):
# Some additional twitter specific properties

等等...

通过使用 PolyModel 作为基类,您可以执行 AuthLogin.query().filter(AuthLogin.user_key == user.key) 并获取为该用户定义的所有身份验证类型共享相同的基类AuthLogin。您需要这个,否则您将不得不依次查询每个支持的身份验证类型,因为您无法在没有祖先的情况下进行无种类的查询,在这种情况下,我们不能使用 User 作为祖先因为我们无法对登录 ID 执行简单的 get() 操作。

但是需要注意的是,AuthLogin 的所有子类都将在“AuthLogin”键中共享相同的类型,因此您仍然需要连接键 id 的 auth_provider 和 auth_type,以便确保您拥有唯一的键。例如。

dev~fish-and-lily> from google.appengine.ext.ndb.polymodel import PolyModel
dev~fish-and-lily> class X(PolyModel):
... pass
...
dev~fish-and-lily> class Y(X):
... pass
...
dev~fish-and-lily> class Z(X):
... pass
...
dev~fish-and-lily> y = Y(id="abc")
dev~fish-and-lily> y.put()
Key('X', 'abc')
dev~fish-and-lily> z = Z(id="abc")
dev~fish-and-lily> z.put()
Key('X', 'abc')
dev~fish-and-lily> y.key.get()
Z(key=Key('X', 'abc'), class_=[u'X', u'Z'])

dev~fish-and-lily> z.key.get()
Z(key=Key('X', 'abc'), class_=[u'X', u'Z'])

这就是您遇到的问题。通过添加提供程序类型作为 key 的一部分,您现在可以获得不同的 key 。

dev~fish-and-lily> z = Z(id="Zabc")
dev~fish-and-lily> z.put()
Key('X', 'Zabc')
dev~fish-and-lily> y = Y(id="Yabc")
dev~fish-and-lily> y.put()
Key('X', 'Yabc')
dev~fish-and-lily> y.key.get()
Y(key=Key('X', 'Yabc'), class_=[u'X', u'Y'])
dev~fish-and-lily> z.key.get()
Z(key=Key('X', 'Zabc'), class_=[u'X', u'Z'])
dev~fish-and-lily>

我认为这对您来说没有任何不方便的模型。

这一切都有意义吗;-)

关于google-app-engine - 是否可以将两个字段设置为ndb中实体的索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17433607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com