如何在 Appengine 中保留数据存储实体的版本历史记录

Posted

技术标签:

【中文标题】如何在 Appengine 中保留数据存储实体的版本历史记录【英文标题】:How to keep version history of datastore entities in Appengine 【发布时间】:2011-09-08 13:45:55 【问题描述】:

我将实体 A 存储在 appengine 上的数据存储区中。 A 的 id 类型为 Long。我想保留对 A 字段所做的所有更改的历史记录。在实体上执行此类版本的最佳实践是什么?我更喜欢与 A 的子类一起工作并且尽可能自动化的解决方案。

谢谢!

【问题讨论】:

Java 还是 Python?如果是 Java,您使用的是什么数据访问框架? 【参考方案1】:

我们正在为我们的一款 AppEngine 应用做类似的事情。我们发现的唯一有效方法是,拥有一个作为您的版本的实体 B,而实体 A 保留一个键列表。

然后,我们在 REST 服务中使用 ETags 来识别我们的客户获取哪个版本的副本。

【讨论】:

你如何查询所有 A 的最新版本(来自我的原始示例) 我们保留第二个属性链接到最新版本以避免查询时间。【参考方案2】:

您可以创建一个实体链接列表,其中每个实体有两个引用:一个指向其先前版本,一个指向下一个版本。当然,您必须自己维护这些引用。实体的最新版本将是不引用下一个版本(或空/空引用)的实体。

根据您的用例,您可能还想研究仅存储实体的两个版本之间差异的方法(如果更改很小而实体很大)。

【讨论】:

【参考方案3】:

有很多方法可以做到这一点。

如果您想要一种不需要数据模型中更多类的方法,您可以使用 parent 属性来编写版本和祖先查询,以便读取最新版本。

这是一个使用 Python GAE 中的 ndb.Model 和 webapp2 框架在 wiki 页面中如何工作的示例:

模型可能是:

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()

【讨论】:

以上是关于如何在 Appengine 中保留数据存储实体的版本历史记录的主要内容,如果未能解决你的问题,请参考以下文章

AppEngine 数据存储区查询具有给定属性的所有实体 (Java)

是否可以为 appengine 数据存储实体获取 Google 电子表格的数据源 URL?

App Engine:如何“重置”数据存储区?

AppEngine 数据存储错误 - 索引未同步

Google AppEngine (GAE) - 完整的对象键

在 Appengine 数据存储中设置操作