Python 实体组、引用属性或键作为字符串
在gae平台上构建一些应用程序之后,我通常在每个应用程序的数据存储中使用不同模型之间的一些关系。我经常发现自己需要查看同一父项的记录(比如将所有条目与同一父项匹配) 从一开始,我就使用db.ReferenceProperty来处理关系,如:Python 实体组、引用属性或键作为字符串,python,google-app-engine,google-cloud-datastore,Python,Google App Engine,Google Cloud Datastore,在gae平台上构建一些应用程序之后,我通常在每个应用程序的数据存储中使用不同模型之间的一些关系。我经常发现自己需要查看同一父项的记录(比如将所有条目与同一父项匹配) 从一开始,我就使用db.ReferenceProperty来处理关系,如: class Foo(db.Model): name = db.StringProperty() class Bar(db.Model): name = db.StringProperty() parentFoo = db.Refer
class Foo(db.Model):
name = db.StringProperty()
class Bar(db.Model):
name = db.StringProperty()
parentFoo = db.ReferanceProperty(Foo)
fooKey = someFooKeyFromSomePlace
bars = Bar.all()
for bar in bar:
if bar.parentFoo.key() == fooKey:
// do stuff
但最近我放弃了这种方法,因为bar.parentFoo.key()
每次都会生成一个子查询来获取Foo。我现在使用的方法是将每个Foo
键作为字符串存储在Bar.parentFoo
上,这样我可以将其与someFooKeyFromSomePlace
进行字符串比较,并消除所有子查询开销
现在我开始研究实体组,想知道这是否是更好的方法?我真的不知道如何使用它们
至于以上两种方法,我想知道使用它们有什么缺点吗?可以使用存储的密钥字符串返回并在***中咬我。最后但并非最不重要的是,有没有更快的方法来实现这一点?提示:
替换
bar.parentFoo.key() == fooKey
与
Bar.parentFoo.get_value_for_datastore(bar) == fooKey
为了避免额外的查找,只需从ReferenceProperty
> P>当您设计模块时,还需要考虑是否要在事务中保存此项。但是,仅当需要使用事务时才执行此操作 另一种方法是指定父对象,如下所示:
from google.appengine.ext import db
class Foo(db.Model):
name = db.StringProperty()
class Bar(db.Model):
name = db.StringProperty()
def _save_entities( foo_name, bar_name ):
"""Save the model data"""
foo_item = Foo( name = foo_name )
foo_item.put()
bar_item = Bar( parent = foo_item, name = bar_name )
bar_item.put()
def main():
# Run the save in a transaction, if any fail this should all roll back
db.run_in_transaction( _save_transaction, "foo name", "bar name" )
# to query the model data using the ancestor relationship
for item in bar_item.gql("WHERE ANCESTOR IS :ancestor", ancestor = foo_item.key()).fetch(1000):
# do stuff
我不确定您想用这个示例代码块做什么,但我感觉它可以通过以下方式完成:
bars = Bar.all().filter("parentFoo " = SomeFoo)
对于实体组,它们主要用于在事务中更改多个内容,因为appengine仅将其限制为同一组中的实体;此外,appengine允许使用祖先过滤器(),这可能很有用,具体取决于您需要做什么。有了上面的代码,如果将Bar的父级设置为Foo,您还可以非常轻松地使用祖先查询
如果您的目的仍然需要大量的“子查询”,那么Nick Johnson在这里介绍了一种简洁的预取模式:它基本上以一个巨大的get而不是一堆小get的形式获取实体集中所需的所有属性,从而消除了大量的开销。但是请注意他的警告,特别是关于在使用此预取方法时更改实体属性的警告
虽然不是很具体,但这就是我能给你的全部信息,直到你更确切地说出你在这里到底想做什么。 < P>我想你也应该考虑一下。这将帮助您获取单个父实体的所有子实体。 宝马=汽车(品牌=“宝马”) bmw.put()
更多建模参考。您可以引用此是否有任何原因不使用
Bar.all().filter(“parentFoo=,fooKey)
,或者这仅仅是因为您简化了此问题?仅针对以下问题:)双重提示:如果您仅使用值进行键比较,请使用KeyProperty而不是ReferenceProperty。如何避免额外的查找?我的意思是get\u value\u for\u datastore
听起来像是对数据库的查询。我可能弄错了。get\u value\u for_datastore
只获取存储在ReferenceProperty
本身中的键,因此不需要数据存储RPC。同样,Calvin的方法通过完全取消ReferenceProperty
取消引用的魔力来避免查找,因此,您可以从数据存储中显式地获取相关实体,而无需借助bar.parentFoo
Nice,它会派上用场。但不幸的是,我将所有的条
与同一个父项进行了比较,并将其放入了自己的列表中。因此,检查它是否将foo1作为父对象,并将其放入foo1List,依此类推。使用run\u-in\u-transaction
而不是调用\u-save\u-transaction()
?我已经更新了代码,使之更清晰一些,即_-save\u-entities()将尝试保存Foo和Bar,但如果Bar方法未能保存,则会保留孤立的Foo实体。当在事务中运行时,如果其中一个保存失败,那么两个保存都将回滚,并且不会向Bigtable提交任何内容。感谢链接,它提供了很多帮助。这个小问题我不知道如何更具体。我在寻找指针,从某种一般意义上说,如何存储模型之间的关系。然后用不同的方法进行撤退。
lf = Wheel(parent=bmw,position="left_front")
lf.put()
lb = Wheel(parent=bmw,position="left_back")
lb.put()
bmwWheels = Wheel.all().ancestor(bmw)