我已经开始研究使用Google数据存储区的现有项目,其中对于某些实体类型,每个实体都被分配了相同的祖先。例如:
class BaseModel(ndb.Model):
@classmethod
def create(cls, **kwargs):
return cls(parent=cls.make_key(), **kwargs)
@classmethod
def make_key(cls):
return ndb.Key('Group', cls.key_name())
class Vehicle(BaseModel):
@classmethod
def key_name(cls):
return 'vehicle_group'
所以键最终看起来像这样:
Key(Group, 'vehicle_group', Vehicle, 5068993417183232)
没有“组”或实体“vehicle_group”这样的类型,但在这些文档中没有问题:"note that unlike in a file system, the parent entity need not actually exist"。
我从阅读中理解,这可能具有性能优势,因为所有实体都在分布式数据存储中共存。
但是将所有这些实体放在一个组中会在我的脑海中产生问题,因为这个项目可以扩展,每秒一次的写入限制将适用于整个类型。该组似乎没有任何交易原因。
项目中没有人知道为什么它最初是这样做的。我的问题是:
答案 0 :(得分:3)
在单个实体组内对许多实体进行分组提供了至少2个我能想到的优势:
对于某些应用程序,1个写入/秒/组限制可能根本不是可扩展性问题(例如,想一次读取很多类型的应用程序,或者每次写入1次的应用程序)秒绰绰有余。)
至于机械师,(独特的)父母"实体"该组的密钥是ndb.Key('Group', "xxx_group")
密钥(其中包含" xxx_group"密钥ID)。相应的"实体"或者它的模型不需要存在(除非需要创建实体本身,看起来并非如此)。父键仅用于建立组"命名空间"在数据存储区中,如果你想要的话。
您可以在Entity Keys documentation的示例中看到某种类似的用途,查看Message
使用情况(Message
只是一个"父"实体祖先路径,但不是根实体):
类修订版(ndb.Model): message_text = ndb.StringProperty()
ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '1') ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '2') ndb.Key('Account', 'larry@foo.com', 'Message', 456, 'Revision', '1') ndb.Key('Account', 'larry@foo.com', 'Message', 789, 'Revision', '2')
...
请注意,Message不是模型类。这是因为我们是 使用Message纯粹作为一种方式对Revisions进行分组,而不是存储数据。
答案 1 :(得分:2)
这可能是为了在组内实现强一致性查询。正如你所指出的那样,这种设计有......缺点。
如果这只是参考数据(即Read many write one),可能会减轻一些负面因素,但也会使正面无效(即如果数据不经常更新,则最终一致性不是问题)。