Reputation: 5389
I'm storing an Entity A in my datastore on appengine. A has an id of type Long. I'd like to keep a history of all changes made to A's fields. What are the best practices to doing this type of version ing on entities? I'd prefer a solution that works well with subclasses of A and is as automatic as possible.
Thanks!
Upvotes: 9
Views: 3042
Reputation: 6389
There are a lot of ways to do that.
If you want one way that do not require more classes in the data model, you can use parent attribute for write the versions and ancestor query with order to read the latest version.
Here is a example of how this could work in a wiki page using ndb.Model and webapp2 framework in Python GAE:
The model could be:
class WikiPage(ndb.Model):
title = ndb.StringProperty(required = True)
text = ndb.TextProperty(required = True)
datetime = ndb.DateTimeProperty(auto_add_now = True)
The handle could be:
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()
Upvotes: 0
Reputation: 754
You could create a linked list of entities, where each entity has two references: one to its previous version and one to the next version. You have to maintain those references yourself, of course. The most recent version of an entity will be the one without a reference to a next version (or an empty/null reference).
Depending on your use case you might also want to look at ways to only store the differences between two version of an entity (if changes are small and entities are large).
Upvotes: 2
Reputation: 3075
We are doing something similar for one of our AppEngine apps. The only efficient way we found was, have an Entity B that are your versions, and Entity A keeps a list of keys.
We then use ETags in our REST services to identify which version our client gets a copy of.
Upvotes: 0