Db.ReferenceProperty() vs ndb.KeyProperty в приложении Engine
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)
- Чтобы получить 'manager_name' с экземпляром команды, мы используем имя team_ins.manager_.
- Чтобы получить "команды", которые управляются конкретным экземпляром пользователя, мы используем user_instance.teams и итерацию.
Разве это не выглядит легко и понятно?
Выполняя то же самое, используя NDB, мы должны изменить
db.ReferenceProperty(UserProf, collection_name = 'teams') → ndb.KeyProperty(kind = UserProf)
- team_ins.manager_name.get() предоставит вам имя менеджера
-
Чтобы получить всю команду, которая является ядром конкретного пользователя, мы должны сделать
для команды в Team.query(Team.manager_name == user_ins.key): (Форматирование здесь не работает)
print "team name:", team.name
Как вы можете видеть, что подобные сценарии выглядят проще и читабельнее в db, чем ndb.
- В чем причина удаления ReferenceProperty в ndb?
- Даже запрос db user_instance.teams сделал бы то же самое, что и в ndb for loop. Но в ndb мы явно упоминаем использование для цикла.
- Что происходит за кулисами, когда мы делаем user_instance.teams?
Спасибо заранее.
Ответы
Ответ 1
Тим объяснил это хорошо. Мы обнаружили, что общий анти-шаблон использовал ссылочные свойства и загружал их по одному, потому что обозначение "entity.property1.property2" не дает понять, что первая точка вызывает операцию "получить" базу данных. Поэтому мы сделали это более очевидным, заставив вас написать "entity.property1.get(). Property2", и мы упростили пакетную предварительную выборку (без сложного решения из блога Nick), просто сказав: "entity.property1.get_async()" для группы сущностей - это очередность одной операции получения пакета без блокировки для результата, а когда вы ссылаетесь на какое-либо из этих свойств с помощью "entity.property1.get(). property2", это не приведет к запуску другого но просто ждет, когда эта партия завершится (и во второй раз вы это сделаете, пакетный сбор уже завершен). Также этот способ интеграции в процесс и memcache предоставляется бесплатно.
Ответ 2
Я не знаю ответа о том, почему Guido не реализовал ссылочное свойство.
Однако я нашел потраченное много времени, используя pre_fetch_refprops http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine (предварительно выбирает все ссылочные свойства, захватывая все ключи с помощью get_value_for_datastore,), а затем он делает get_multi на клавишах.
Это было значительно более эффективно.
Также, если ссылка на объект не существует, вы получите ошибку при попытке получить объект.
Если вы мариновали объект, у которого были ссылки, вы в конечном итоге травили намного больше, чем вы, вероятно, тоже планировали.
Итак, я нашел, за исключением одного случая, когда у вас есть единая сущность, и вы хотели захватить ссылочный объект с помощью типа типа .name, вам нужно было перепрыгнуть через всевозможные обручи, чтобы предотвратить выбор привязанного объекта.