Я думаю, что вы неявно спрашиваете, поддерживает ли Google App Engine JOIN, чтобы избежать проблемы N + 1 select .
Google App Engine не поддерживает JOIN напрямую, но позволяет вам определить one to many relationship
, используя ReferenceProperty .
class Author(db.Model):
name = db.StringProperty()
class Book(db.Model):
title = db.StringProperty()
author= db.ReferenceProperty(Author)
В вашем конкретном сценарии с двумя запросами запросов первый должен получить автора:
author = Author.all.filter('name =' , 'fooauthor').get()
, а второй - найтивсе книги данного автора:
books = Book.all().filter('author=', author).fetch(...)
вы можете получить тот же результат общего SQL-запроса, который использует JOIN.
Проблема N + 1 можетнапример, появляются, когда мы хотим получить 100 книг, каждая с именем автора:
books = Book.all().fetch(100)
for book in books:
print book.author.name
В этом случае нам нужно выполнить 1 + 100 запросов, один для получения списка книг и 100 для разыменования всехавторы возражают, чтобы получить имя автора (этот шаг неявно выполняется в операторе book.author.name
).
Один из распространенных методов решения этой проблемы - использование метода get_value_for_datastore
, который возвращает ключ указанного автора для данного объекта.книга без дессылка на него (т. е. выборка из хранилища данных):
author_key = Book.author.get_value_for_datastore(book)
В этой теме есть блестящее сообщение в блоге , которое вы можете прочитать.
Этот метод, начиная с author_key
список, предварительно выбирает объекты авторов из хранилища данных, устанавливая каждый из них в соответствующую книгу сущностей.
При таком подходе экономится много обращений к хранилищу данных, и практически * избегает N + 1 проблема.
* теоретически, на книжной полке со 100 книгами, написанными 100 разными авторами, нам все равно придется вызывать хранилище данных 100 + 1 раз
Отвечая на вашвопрос:
- Google App Engine не поддерживает нетерпеливое извлечение
- Существуют методы (не из коробки), которые помогают избежать страшных N + 1 задача