Python:在数据存储中建模一对一关系

Python:在数据存储中建模一对一关系,python,google-app-engine,data-structures,google-cloud-datastore,Python,Google App Engine,Data Structures,Google Cloud Datastore,假设我们有两个模型:User和Token。一个用户可能只有一个令牌,而令牌只能属于一个用户 来自关系数据库,下面的方法似乎可以做到这一点: 这当然也会创建User.token\u set,这是一个db.Query。 但是我真的很想用,User.token而不是User.token\u set.get()来访问令牌,那么 class User(db.Model): name = db.StringProperty() token = db.ReferenceProperty(Tok

假设我们有两个模型:
User
Token
。一个用户可能只有一个
令牌
,而
令牌
只能属于一个用户

来自关系数据库,下面的方法似乎可以做到这一点:

这当然也会创建
User.token\u set
,这是一个
db.Query
。 但是我真的很想用,
User.token
而不是
User.token\u set.get()
来访问令牌,那么

class User(db.Model):
    name = db.StringProperty()
    token = db.ReferenceProperty(Token)

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)
现在我可以以双向方式访问它们:
User.token
&
User.owner
。我已经自动创建了
.token\u集
用户集

这有什么问题吗?在逻辑方面,在性能方面

也许我不应该有两个模特。实际上,它们都包含四个或五个属性。他们应该是一个吗?什么时候一对一的关系应该被抛弃,只是合并成一个模型


谢谢你的任何意见

这是appengine数据存储。这不是sql。您应该将系统使用的数据分组在一起。假设您有用户和令牌一起使用的地方,并且由于多对一不存在任何问题,因此这些可以放在同一个模型实例中。这将为您提供更好的性能(例如,通过令牌更简单地检索用户)和更容易的一致性处理(更新令牌和用户将在单个事务中)

我不知道这里是否可以接受自链接,所以如果不能,也许有人会编辑这个,但我写这篇文章是为了收集我在数据存储方面的经验。你可能会发现它很有用


[编辑:思考这个问题的一种方式:你不是在建模数据。你在编写一个旨在扩展的系统。这——而不是建模数据——是驱动一切的因素。我不是说这是一个好主意,但appengine就是这么做的。如果你的主要任务是建模数据——例如,如果你想让多个应用程序使用你的以不同的方式获取数据-那么您不应该使用appengine。]

将令牌引用添加到用户类有其优点和缺点。这样做的好处是,您将在令牌检索中获得更好的性能。缺点是,插入数据时,您将需要更多的事务

user = User(name='john').put()
token = Token(name='somehash', user=user).put()
user.token = token
user.put()
在删除令牌时,还必须处理空引用

如果语法糖是您想要的,也许您可以使用类装饰器:

class User(db.Model):
    name = db.StringProperty()

    @property
    def token(self):
        if not hasattr(self, '_token_cached'):
            setattr(self, '_token_cached', self.token_set.get())
       return self._token_cached
class User(db.Model):
    name = db.StringProperty()

    @property
    def token(self):
        if not hasattr(self, '_token_cached'):
            setattr(self, '_token_cached', self.token_set.get())
       return self._token_cached