Группы объектов, ReferenceProperty или ключ в виде строки - PullRequest
3 голосов
/ 25 марта 2011

После создания нескольких приложений на платформе 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

Но в последнее время я отказался от этого подхода, поскольку bar.parentFoo.key() делает подзапрос, чтобы каждый раз получать Foo.Подход, который я сейчас использую, заключается в том, чтобы хранить каждый ключ Foo в виде строки на Bar.parentFoo, и таким образом я могу сравнить строку с someFooKeyFromSomePlace и избавиться от всех издержек подзапроса.

Теперь я 'Я начал изучать группы сущностей и задумался, а не лучше ли это?Я не могу понять, как их использовать.

А что касается двух приведенных выше подходов, мне интересно, есть ли недостатки в их использовании?Может использовать сохраненный ключ возврата строки и укусил меня в * * *.И, наконец, что не менее важно, есть ли более быстрый способ сделать это?

Ответы [ 4 ]

3 голосов
/ 25 марта 2011

Совет:

заменить ...

bar.parentFoo.key() == fooKey

на ...

Bar.parentFoo.get_value_for_datastore(bar) == fooKey

Чтобы избежать дополнительного поиска и просто получить ключ из ReferenceProperty

См. Класс недвижимости

2 голосов
/ 25 марта 2011

Я думаю, вы должны рассмотреть это также. Это поможет вам выбрать все дочерние объекты одного родителя. bmw = Автомобиль (марка = "BMW") 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 моделирование

1 голос
/ 25 марта 2011

Я не уверен, что вы пытаетесь сделать с этим примером блока кода, но я чувствую, что это может быть достигнуто с помощью:

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

Что касается групп сущностей, они в основном используются, если вы хотите изменить несколько вещей в транзакциях, поскольку appengine ограничивает это только для сущностей в пределах одной и той же группы; Кроме того, appengine допускает фильтры предков (http://code.google.com/appengine/docs/python/datastore/queryclass.html#Query_ancestor), которые могут быть полезны в зависимости от того, что вам нужно сделать. Используя приведенный выше код, вы также можете очень легко использовать запрос предка, если для родительского элемента Bar задано Foo.

Если ваши цели все еще требуют большого количества «подзапросов», как вы их сформулировали, здесь есть аккуратный шаблон предварительной выборки, который обрисовывает в общих чертах Ник Джонсон: http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine, который в основном выбирает все свойства, которые вам нужны в вашей сущности, заданной как один гигант получает вместо кучки крошечных, что избавляет от многих накладных расходов. Однако обратите внимание на его предупреждения, особенно касающиеся изменения свойств объектов при использовании этого метода предварительной выборки.

Не очень конкретно, но это вся информация, которую я могу вам дать, пока вы не будете более конкретно знать, что именно вы пытаетесь сделать здесь.

1 голос
/ 25 марта 2011

При разработке своих модулей вам также необходимо решить, хотите ли вы сохранить это в транзакции. Тем не менее, делайте это только если вам нужно использовать транзакции.

Альтернативный подход - назначить родителя следующим образом:

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
...