我对使用python ndb有些怀疑。我正在使用proto数据存储区。我有一个用户类
class User( EndpointsModel ):
name = ndb.StructuredProperty( Name, required=True )
dateOfBirth = ndb.DateProperty(required=True)
userName = ndb.StringProperty( required=True )
emailId = ndb.StringProperty( required=True )
我想根据用户名获取用户实体。当我创建一个新的User对象并执行
时user.id = username
我收到错误" ID必须是整数。",我该如何克服这个问题。 user.get_by_id()也会快于 User.query(User.username == username)?
如果我希望所有用户名都是唯一的,我是否必须创建一个用户名实体,并检查新用户是否已经存在,或者是否存在其他整洁有效的用户这样做的方法。
答案 0 :(得分:4)
听起来您希望实体的唯一键包含并可从用户名中重现,这是一项常见且有用的事情。
要创建具有特定ID的User实体,必须在调用构造函数时设置ID:
username = 'foo'
user = User(id=username)
user.put()
这构造了一个新的实体对象,其键为User: foo
(其中键具有一个路径部分,其类型名称为User
,字符串foo
的ID)。 put()
调用会将其保存到数据存储区。
要获取给定用户名的实体,请构建Key
,然后尝试get()
:
key = ndb.Key('User', username)
user = key.get()
if not user:
# ....
如果它不存在,通常会将这些内容放在一起为给定用户名创建User
实体:
key = ndb.Key('User', username)
user = key.get()
if not user:
user = User(id=username)
user.put()
建议的做法是在数据存储区事务中执行此操作,因此尝试为同一用户名创建第一个User
实体的两个客户端不会在不知情的情况下互相攻击。
将用户名放在密钥中可保证唯一性。是的,通过密钥获取比通过属性查询更快。查询涉及多个步骤以将结果作为键列表获取,然后获取结果实体,即使只有一个结果。您可能希望将用户名存储为索引属性,以防您需要其他类型的查询,但是获取实体或仅执行存在检查仅使用密钥。
答案 1 :(得分:0)
您是如何创建用户实例的?这样做的正确方法是:
newUser = User(id=your_id)
您根本不需要使用newUser.id
,它将无法使用。如果您使用现有ID创建新用户,它将替换数据库中的旧用户。您必须找到一种方法来跟踪您使用的ID或给它们不同的父键,在这种情况下,如果父母不同,您可以复制ID。
关于你的第二个问题,我已经阅读了get_by_id()
类,它实际上做的是它使用了一个查询。但是,如果您要自己使用查询,则必须确保获取1个实例并从列表中获取第一个元素fetch()
(User.query().fetch(1)[0]
)。使用get_by_id()
会更容易,或者如果您有密钥,则使用key.get()
。