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

raj*_*jpy 15 python google-app-engine app-engine-ndb google-cloud-datastore

ReferenceProperty在处理两个模块之间的引用时非常有用.Fox例子:

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)
Run Code Online (Sandbox Code Playgroud)
  • 要使用团队实例获取"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
    
    Run Code Online (Sandbox Code Playgroud)

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

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

提前致谢..

Gui*_*sum 26

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

  • @Tim和Guido,您能否建议使用类似于http://code.google.com/p/google-app-engine-samples/中的ndb编写的任何示例应用程序.以及在基于ndb的应用程序中遵循的最佳实践.这会有很大帮助.谢谢. (3认同)

Tim*_*man 7

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

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

这样效率更高.

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

如果你腌制了一个带有参考物的物体,你最终会腌制比你可能计划的更多.

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