【问题标题】:NDB Modeling One-to-one with KeyProperty与 KeyProperty 一对一的 NDB 建模
【发布时间】:2013-04-20 01:16:24
【问题描述】:

我对 ndb 很陌生,但我已经明白我需要重新连接大脑中的某个区域来创建模型。我正在尝试创建一个简单的模型——只是为了理解如何设计一个 ndb 数据库——具有一对一的关系:例如,一个用户和他的信息。经过大量搜索 - 找到了文档,但很难找到不同的示例 - 并进行了一些实验(以几种不同的方式建模和查询),这是我找到的解决方案:

from google.appengine.ext import ndb

class Monster(ndb.Model):
    name = ndb.StringProperty()

    @classmethod
    def get_by_name(cls, name):
        return cls.query(cls.name == name).get()

    def get_info(self):
        return Info.query(Info.monster == self.key).get()

class Info(ndb.Model):
    monster = ndb.KeyProperty(kind='Monster')
    address = ndb.StringProperty()

a = Monster(name = "Dracula")
a.put()

b = Info(monster = a.key, address = "Transilvania")
b.put()

print Monster.get_by_name("Dracula").get_info().address

NDB 不接受连接,因此我们想要的“连接”必须使用类方法和属性来模拟。使用上述系统,我可以通过第一个数据库中的唯一属性(在本例中为“名称” - 假设没有两个同名的怪物)轻松访问第二个数据库(信息)中的属性。

但是,如果我想打印一个包含 100 个怪物名称和各自地址的列表,第二个数据库(信息)将被点击 100 次。

问题:有没有更好的方法对此进行建模以提高性能?

【问题讨论】:

    标签: google-app-engine database-design app-engine-ndb


    【解决方案1】:

    如果它真的是一对一的关系,为什么要创建 2 个模型。鉴于您的示例,地址实体不能与任何怪物共享,所以为什么不将地址详细信息放入怪物中。

    您不这样做是有一些原因的。

    1. 当您只需要几个时,地址可能会变得很大,因此检索 100 个属性的效率会降低 - 尽管项目查询可能会有所帮助。

    2. 您改变主意并希望查看所有生活在特兰西瓦尼亚的怪物——在这种情况下,您将创建地址实体,而怪物将拥有指向该地址的关键属性。当您确定某些怪物可以生活在多个地方时,这显然会失败(狼人 - 伦敦,特兰西瓦尼亚,纽约;-),在这种情况下,您要么在怪物中有重复的 KeyProperty,要么有一个指向怪物的中间实体,并且地址。就你而言,我认为怪物总体上没有那么多记录在案的地址;-)

    此外,如果您通过名称来唯一标识怪物,您应该考虑将名称存储为密钥的一部分。执行 Monster.get_by_id("dracula") 比按名称查询要快。

    正如我在评论中写的(糟糕)。如果上述 1. 成立并且这是真正的一对一关系。然后,我会在创建地址时将地址创建为子实体(Monster 是键中的父/祖先)。这使您可以,

    1. 允许其他实体指向地址,
    2. 如果您创建了一堆子实体,请使用单个 祖先查询)。 3 如果你有怪物并且它拥有实体 这又是一个祖先查询。
    3. 如果您有一堆实体 仅当 Monster 实例存在且它们不存在时才应存在 孩子,那么你必须对所有实体类型进行查询 KeyProperty 的匹配键,如果这些实体不匹配 PolyModels,那么您必须为每个实体执行查询 类型(并且知道您需要对给定实体执行查询, 这涉及某种类型的注册表或硬编码)

    【讨论】:

    • '@Tim' 感谢您的回答。原因 1 是正确的。信息会变大,我会添加很多其他属性,比如怪物所在的城市、国家、电话号码等,我每次查询怪物时都不需要它们。我会将其他模型链接到它们,并带有 last_appearance、eat_people(布尔值)之类的信息。我没有将名称存储为密钥的一部分,因为我希望能够更改它(例如某些网站中的用户名)。但是,我也可以只添加“名称”属性不能更改且必须是唯一的规则。
    • 好的,鉴于此,我会将地址设为子实体(在构造时指定怪物是父实体,可能具有已知的键名)。它已经知道没有怪物存在的业务,其他实体可以直接引用它。这可能是一大堆子实体,然后您可以使用单个祖先查询来获取它们。
    • 好的,蒂姆,太好了!由于我是 ndb 的新手,并且文档中缺少实际示例,所以您能向我展示代码吗?我一直在交互式控制台中处理孩子/父母的关系,但我一无所获,我不太了解它是如何工作的。谢谢!
    【解决方案2】:

    我怀疑您可能正在尝试使用以下链接中描述的元素来实现 看看“对多个键或实体的操作”“扩展模型”“模型挂钩”

    https://developers.google.com/appengine/docs/python/ndb/entities

    (这可能更像是评论而不是答案)

    【讨论】:

    • 好的,所以我有一个一对一的关系,我想从两个模型中检索一个包含属性的列表。最好的模式是什么?有很多方法可以做到这一点,Tim(上图)已经说过使用 ID 检索实体比查询更快。你看,我想念的是具有常见模式的 ndb 文档。
    猜你喜欢
    • 2012-12-05
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多