实体组,ReferenceProperty或键作为字符串

时间:2011-03-24 21:14:45

标签: 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.ReferanceProperty(Foo)

fooKey = someFooKeyFromSomePlace
bars = Bar.all()
for bar in bar:
    if bar.parentFoo.key() == fooKey:
        // do stuff

但是最近我放弃了这个approch,因为bar.parentFoo.key()每次都会生成一个子查询来获取Foo。我现在使用的方法是将每个Foo键存储为Bar.parentFoo上的字符串,这样我就可以将其与someFooKeyFromSomePlace进行字符串比较,并消除所有子查询开销。

现在我开始关注实体组,并想知道这是否是更好的方法?我无法弄清楚如何使用它们。

至于上述两种方法,我想知道使用它们有什么缺点吗?可以使用存储的密钥字符串回来并在* * *中对我进行排序。最后但并非最不重要的是有更快的方法来做到这一点吗?

4 个答案:

答案 0 :(得分:3)

提示:

取代...

bar.parentFoo.key() == fooKey

...与

Bar.parentFoo.get_value_for_datastore(bar) == fooKey

要避免额外查找,只需从ReferenceProperty

中获取密钥

请参阅Property Class

答案 1 :(得分:2)

我认为你也应该考虑这一点。这将帮助您获取单个父级的所有子实体。     宝马=汽车(品牌=“宝马”)     bmw.put()

lf = Wheel(parent=bmw,position="left_front")
lf.put()

lb = Wheel(parent=bmw,position="left_back")
lb.put()

bmwWheels = Wheel.all().ancestor(bmw)

有关建模的更多参考。你可以参考这个Appengine Data modeling

答案 2 :(得分:1)

在设计模块时,还需要考虑是否希望能够在事务中保存它。但是,只有在需要使用事务时才这样做。

另一种方法是像这样分配父母:

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

答案 3 :(得分:1)

我不确定您尝试使用该示例代码块做了什么,但我觉得可以通过以下方式完成:

bars = Bar.all().filter("parentFoo " = SomeFoo)

对于实体组,如果您想要在事务中更改多个内容,则主要使用它们,因为appengine仅限于同一组内的实体;此外,appengine允许祖先过滤器(http://code.google.com/appengine/docs/python/datastore/queryclass.html#Query_ancestor),这可能是有用的,这取决于你需要做什么。使用上面的代码,如果将Bar的父级设置为Foo,则可以非常轻松地使用祖先查询。

如果你的目的仍然需要很多" subquerying"正如你所说,尼克约翰逊在这里概述了一个简洁的预取模式:http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine它基本上将你实体集中所需的所有属性作为一个巨大的获取而不是一堆小的,取消了很多开销。但请注意他的警告,特别是在使用此预取方法时更改实体的属性。

不是非常具体,但这是我能给你的所有信息,直到你更具体地了解你在这里尝试做什么。