Google app engine 使用KeyProperty对NDB进行一对一建模

Google app engine 使用KeyProperty对NDB进行一对一建模,google-app-engine,database-design,app-engine-ndb,Google App Engine,Database Design,App Engine Ndb,我对ndb很陌生,但我已经明白我需要重新连接大脑中的某个区域来创建模型。我试图创建一个简单的模型——只是为了理解如何设计ndb数据库——具有一对一的关系:例如,用户和他的信息。在搜索了大量找到的文档后,很难找到不同的示例,并进行了一些实验(以几种不同的方式进行建模和查询),这就是我找到的解决方案: from google.appengine.ext import ndb class Monster(ndb.Model): name = ndb.StringProperty()

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

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


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

如果这确实是一对一的关系,为什么要创建两个模型。鉴于您的示例,地址实体无法与任何怪物共享,因此为什么不将地址详细信息放入怪物中

你为什么不这么做是有原因的

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

  • 你改变主意,你想看到所有生活在特兰西瓦尼亚的怪物——在这种情况下,你将创建地址实体,怪物将拥有指向地址的关键属性。当你发现一些怪物可以生活在多个地方(狼人-伦敦、特兰西瓦尼亚、纽约;-)时,这显然是失败的,在这种情况下,你要么在怪物中有一个重复键属性,要么有一个指向怪物和地址的中间实体。在你的情况下,我不认为怪物总的来说有那么多文档化的地址;-)

  • 此外,如果您通过名称唯一标识怪物,则应该考虑将名称存储为密钥的一部分。做一个怪物。按id获取(“德古拉”)比按名字查询要快

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

  • 允许其他实体指向该地址
  • 如果创建一组子实体,请使用单个 祖先查询)。3如果你有怪物和它拥有的实体 这也是一个祖先查询
  • 如果你有一堆实体 只有当怪物实例存在而它们不存在时才应该存在 子类,则必须使用 KeyProperty与键匹配,如果这些实体不匹配 然后,您必须对每个实体执行查询 键入(并知道需要对给定实体执行查询), 这涉及某种类型的注册表或硬编码)

  • 我怀疑你所尝试的可以通过使用下面链接中描述的元素来实现 请看“对多个键或实体的操作”“Expando模型”“模型挂钩”


    (这可能更多的是评论而不是回答)

    “@Tim”谢谢你的回答。理由1是正确的。信息会变得很大,我会添加很多其他属性,比如monster的城市、国家、电话号码等,我不需要每次查询monster时都使用它们。我会把其他模型和它们联系起来,比如最后一次出现,吃人(布尔值)。我没有将名称存储为密钥的一部分,因为我希望能够更改它(如某些网站中的用户名)。但是,我也可以添加“name”属性不能更改且必须唯一的规则。好的,考虑到这一点,我会将地址设置为子实体(在构造时指定monster为父实体,可能使用已知的密钥名)。它已经知道业务存在而没有怪物,其他实体可以直接引用它。可以是一大堆子实体,然后您可以通过单个祖先查询获取它们!由于我是ndb新手,并且文档缺少实际示例,您能给我看一下代码吗?我一直在玩互动控制台中的儿童/家长关系,但我一无所获,我不太了解它是如何工作的。谢谢好的,我有一个一对一的关系,我想从两个模型中检索一个包含属性的列表。最好的模式是什么?有很多方法可以做到这一点,Tim(上面)已经说过,使用ID检索实体比查询要快。你看,我错过的是一个具有通用模式的ndb文档。