Массовые обновления в хранилище данных Google App Engine

Каков правильный способ массового обновления объектов в хранилище данных Google App Engine? Можно ли это сделать без необходимости получать объекты?

Например, какой бы GAE эквивалентен этому в SQL:

UPDATE dbo.authors
SET    city = replace(city, 'Salt', 'Olympic')
WHERE  city LIKE 'Salt%';

Ответ 1

Нет прямого перевода. У хранилища данных действительно нет понятия обновлений; все, что вы можете сделать, это перезаписать старые объекты с новым объектом с тем же адресом (ключ). Чтобы изменить объект, вы должны извлечь его из хранилища данных, изменить его локально и затем сохранить его.

Также нет эквивалента оператору LIKE. В то время как сопоставление подстановочных подстановок возможно с некоторыми трюками, если вы хотите сопоставить "% Salt%", вам нужно будет прочитать каждый отдельный объект в памяти и локально выполнить сравнение строк.

Таким образом, это не будет столь же чистым и эффективным, как SQL. Это компромисс с большинством хранилищ распределенных объектов, и хранилище данных не является исключением.

Таким образом, библиотека картографа доступна для облегчения таких пакетных обновлений. Следуйте примеру и используйте что-то подобное для вашей функции process:

def process(entity):
  if entity.city.startswith('Salt'):
    entity.city = entity.city.replace('Salt', 'Olympic')
    yield op.db.Put(entity)

Существуют другие альтернативы, кроме картографа. Самый важный совет по оптимизации - пакет обновлений. не сохраняйте каждый обновленный объект отдельно. Если вы используете mapper и put puts, это обрабатывается автоматически.

Ответ 2

Нет, это не может быть сделано без извлечения сущностей.

Нет такой вещи, как "максимальный рекорд записи 1000", но, конечно же, есть тайм-аут для любого отдельного запроса - и если у вас есть большие количества объектов для изменения, простая итерация, вероятно, станет фолом этого. Вы могли бы управлять этим путем разделения его на несколько операций и отслеживания с помощью курсора запроса или потенциально с помощью Каркас MapReduce.