#database #google-app-engine #versioning #datastore
#База данных #google-app-engine #управление версиями #хранилище данных
Вопрос:
Я сохраняю объект A в своем хранилище данных в appengine. A имеет идентификатор типа Long. Я хотел бы сохранить историю всех изменений, внесенных в поля A. Каковы наилучшие методы для создания такого типа версий для объектов? Я бы предпочел решение, которое хорошо работает с подклассами A и является максимально автоматическим.
Спасибо!
Комментарии:
1. Java или Python? Если Java, то какую платформу доступа к данным вы используете?
Ответ №1:
Вы могли бы создать связанный список объектов, где у каждого объекта есть две ссылки: одна на его предыдущую версию и одна на следующую версию. Разумеется, вы должны поддерживать эти ссылки самостоятельно. Самой последней версией объекта будет та, в которой нет ссылки на следующую версию (или пустая / нулевая ссылка).
В зависимости от вашего варианта использования вы также можете рассмотреть способы сохранения различий только между двумя версиями объекта (если изменения небольшие, а объекты большие).
Ответ №2:
Мы делаем нечто подобное для одного из наших приложений AppEngine. Единственным эффективным способом, который мы нашли, было создать объект B, который соответствует вашим версиям, а объект A хранит список ключей.
Затем мы используем ETags в наших службах REST, чтобы определить, копию какой версии получает наш клиент.
Комментарии:
1. как выполнить запрос к самой последней версии всех A (из моего исходного примера)
2. Мы сохраняем второе свойство, которое ссылается на самую последнюю версию, чтобы избежать времени запроса.
Ответ №3:
Есть много способов сделать это.
Если вам нужен способ, который не требует дополнительных классов в модели данных, вы можете использовать родительский атрибут для записи версий и запроса предка с целью чтения последней версии.
Вот пример того, как это может работать на вики-странице с использованием ndb.Model и webapp2 framework в Python GAE:
Модель может быть:
class WikiPage(ndb.Model):
title = ndb.StringProperty(required = True)
text = ndb.TextProperty(required = True)
datetime = ndb.DateTimeProperty(auto_add_now = True)
Дескриптор может быть:
class Page(webapp2.RequestHandler):
def get(self, path):
# create the page key from the page id (in this case, the get request path)
page_key = ndb.Key('WikiPage', path)
# query for edited versions
wikipage_edited = WikiPage.query(ancestor=page_key).order(-WikiPage.datetime).get()
# check if wikipage have edited versions
if wikipage_edited:
wikipage = wikipage_edited
# if not, get the original version
else:
wikipage = page_key.get()
# some custom function to render the wikipage
self.render(wikipage)
def post(self):
# you can pass some parameter that indicates the page_id being edited
page_id = self.request.get('page_id')
# check if page_id was sent
if page_id:
wikipage = WikiPage(parent = ndb.Key('WikiPage', page_id),
title = self.request.get('new_title'),
text = self.request.get('new_text'))
# if page_id wasn't sent, it assumes that a new page is being created
else:
# some custom function that create a page id in the way you want
page_id = self.create_a_page_id()
wikipage = WikiPage(id = page_id,
title = self.request.get('title'),
text = self.request.get('text'))
wikipage.put()