Хорошие примеры использования групп сущностей в App Engine с открытым исходным кодом?
Я знаю все подробности о том, как группы сущностей работают в хранилище GAE, но вчера (на встрече App Engine в Пало-Альто), когда докладчик объяснял, как он использует группы сущностей, меня поразило, что я никогда не использовал их в моих собственных приложениях GAE, и я не помню, чтобы они использовались в приложениях GAE с открытым исходным кодом, которые я использовал.
Итак, я подозреваю, что я просто пропустил (не замечая или не запоминая) такие примеры, потому что я просто недостаточно привык к ним, чтобы сразу связать "использование группы сущностей" с "видом решаемых проблем приложения" - и я Думаю, мне следует исправить это, изучая такие источники с этой целью, сосредотачиваясь на том, какую проблему решает использование EG (то есть, почему приложение работает с ним, но не будет работать или не будет работать без него).
Кто-нибудь может предложить хорошие URL-адреса для такого кода? (Эссе также приветствуются, если они сосредоточены на решении проблем на уровне приложений, но не в том случае, если, как и большинство других, которые я видел, они просто сосредотачиваются на деталях работы ЭГ!-).
3 ответа
Основное использование групп объектов заключается в предоставлении средств для обновления более чем одного объекта в транзакции.
Если вам не приходилось их использовать, считайте свои благословения. Либо вы разрабатывали свои модели данных таким образом, чтобы никогда не обновлять две сущности одновременно, чтобы оставаться согласованными, либо они вам нужны, но вам повезло:)
Представьте, что у меня есть тип объекта Invoice и тип объекта LineItem. Один счет может иметь несколько связанных с ним элементов LineItem. В моем объекте Invoice есть поле с именем LastUpdated. Каждый раз, когда LineItem добавляется в мой счет, я хочу сохранить текущую дату в поле LastUpdated.
Моя функция обновления может выглядеть так (псевдокод)
invoice.lastUpdated = now()
lineitem = new lineitem()
invoice.put()
lineitem.put()
Что произойдет, если накладная put() завершится успешно, а lineitem put() завершится неудачей? Моя дата выставления счета покажет, что что-то было обновлено, но фактическое обновление (новый LineItem) не будет там. Решение состоит в том, чтобы поместить оба put() в транзакцию.
Альтернативным решением будет использование запроса для поиска даты последнего вставленного LineItem вместо сохранения этих данных в поле lastUpdated. Но это потребовало бы извлечения как Invoice, так и всех LineItems каждый раз, когда вы хотите знать, когда последний раз добавлялся lineitem, стоило вам драгоценной квоты хранилища данных.
РЕДАКТИРОВАТЬ, ЧТОБЫ ОТВЕТИТЬ НА КОММЕНТАРИИ ПОСТЕРА
Ах. Я думаю, что понимаю ваше замешательство. Приведенные выше пункты устанавливают, почему сделки важны. Но вы говорите, что все еще не заботитесь о группах сущностей, потому что не видите, как они связаны с транзакциями. Но если вы используете db.run-in-action, то вы используете группы сущностей, возможно, даже не осознавая этого! Каждая транзакция включает одну и только одну группу объектов, и любая данная операция может влиять только на объекты, принадлежащие к той же группе. смотрите здесь
"Все операции с хранилищами данных в транзакции должны работать с объектами в одной группе объектов".
Какие вещи вы делаете в ваших транзакциях? Существует множество веских причин использовать транзакции только с одной сущностью, которая по умолчанию находится в собственной группе сущностей. Но иногда вам нужно синхронизировать 2 или более объектов, как в моем примере выше. Если объекты Invoice и LineItem не находятся в одной и той же группе объектов, вы не можете обернуть их изменения в вызов db.run-in-action. Поэтому в любое время, когда вы хотите работать с двумя или более объектами транзакционно, вы должны сначала убедиться, что они находятся в одной группе. Надеюсь, что это делает более понятным, почему они полезны.
Я использовал их здесь. Я устанавливаю свой объект клиента как родительский элемент маркеров карты. Это создает группу сущностей для каждого клиента и дает мне два преимущества:
Получение маркеров клиента происходит намного быстрее, поскольку они физически хранятся вместе с объектом клиента (на том же сервере, вероятно, на том же диске).
Я могу изменить маркеры для клиента в транзакции. Я подозреваю, что причина того, что транзакции требуют, чтобы все объекты, с которыми они работают, были в одной и той же группе, заключается в том, что они хранятся в одном и том же физическом месте, что упрощает реализацию блокировки данных.
Я использовал их здесь, в этой простой вики-системе. Последняя версия страницы всегда является корневой сущностью, а последние версии имеют последнюю версию в качестве предка. Операция копирования выполняется в транзакции, чтобы сохранить согласованность версий и избежать потери версии в случае параллелизма.