App Engine中的db.ReferenceProperty()与ndb.KeyProperty

时间:2013-05-29 06:39:24

标签: python google-app-engine google-cloud-datastore app-engine-ndb

ReferenceProperty在处理两个模块之间的引用时非常有用。福克斯的例子:

class UserProf(db.Model):
    name = db.StringProperty(required=True)

class Team(db.Model):
    manager_name = db.ReferenceProperty(UserProf, collection_name='teams')
    name = db.StringProperty(required=True)
  • 要使用团队实例获取'manager_name',我们使用team_ins.manager_name。
  • 要获得由特定用户实例管理的“团队”,我们使用user_instance.teams并迭代。

它看起来不容易理解吗?

在使用NDB做同样的事情时,我们必须修改

db.ReferenceProperty(UserProf, collection_name='teams') - > ndb.KeyProperty(kind=UserProf)

  • team_ins.manager_name.get()会给你经理姓名
  • 要获得特定用户管理的所有团队,我们必须

    for team in Team.query(Team.manager_name == user_ins.key): 
        print "team  name:", team.name
    

正如您所看到的那样处理这些场景在db中看起来比ndb更容易和可读。

  • 在ndb中删除ReferenceProperty的原因是什么?
  • 甚至db的查询user_instance.teams也会像在ndb的for循环中那样做。但在ndb中,我们明确提到使用for循环。
  • 当我们执行user_instance.teams时,幕后发生了什么?

提前致谢..

2 个答案:

答案 0 :(得分:26)

蒂姆解释得很好。我们发现一个常见的反模式是使用引用属性并一次加载一个,因为符号“entity.property1.property2”并不清楚第一个点导致数据库“get”操作。所以我们通过强迫你编写“entity.property1.get(。。property2”来使它变得更加明显,我们通过简单地说“entity.property1.get_async”更容易进行批量预取(没有Nick的博客的复杂解决方案)。 ()“对于一堆实体 - 这会将单个批处理get操作排队,而不会阻塞结果,当您下次使用”entity.property1.get(。。property2“引用任何这些属性时,这将无法启动另一个获取操作但只是等待该批次完成(第二次执行此操作时,批次获取已经完成)。此外,这种方式在进程和内存缓存集成是免费的。

答案 1 :(得分:7)

我不知道为什么Guido没有实现引用属性的答案。

然而,我发现花了很多时间使用pre_fetch_refprops http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine(通过使用get_value_for_datastore抓取所有键来预取所有引用属性),然后它在键上执行get_multi。

这样效率更高。

此外,如果引用的对象不存在,则在尝试获取对象时会出现错误。

如果你腌制了一个带有参考物的物体,你最终会腌制比你想象的要多得多。

所以我发现除了一个案例,你有单个实体,你想用.name类型访问器获取引用的对象,你必须跳过各种箍,以防止被引用的实体被提取。