Db.ReferenceProperty() vs ndb.KeyProperty в приложении Engine - программирование
Подтвердить что ты не робот

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?

Спасибо заранее.

4b9b3361

Ответ 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, вам нужно было перепрыгнуть через всевозможные обручи, чтобы предотвратить выбор привязанного объекта.