我希望创建一个系统来跟踪 Google App Engine (Python) 上 ndb.Models/Expandos 内容的版本(历史)。
内容可能比较长,版本可能很多,但版本之间的差异可能很小。我希望其他人做过类似的事情,我想知道他们是如何做的,以及哪些原则可以指导设计和开发。
在部署时不知道数据模型的属性是什么(例如“标题”、“内容”、“正文”、“日期”等),但类型是已知的(日期、文本等)。
我最初的想法是安排这样的事情:
from google.appengine.ext import ndb
class Version(ndb.Expando):
version_id = ndb.IntegerProperty()
# dated, etc.
# data properties are not known in advance, hence Expando
class MyDoc(ndb.Model):
head = ndb.KeyProperty(kind=Version)
instance = ndb.kind=Property(kind=Version, repeated=True)
# ^^^ may be a StructuredProperty?
算法的概述是:
保存
每次用户保存文档时,将所有最新数据放入新的 Version
并将 head
指向该实例。
在那一点或之后的某个时间,浏览旧版本并将完整保存更改为差异(以节省空间),例如diff-match-patch .我希望每小时、每天或某个设定时间(或某个设定数量的差异)进行一次完整保存。
正在加载
加载 head
很简单。
旧版本将被标记为完整保存或差异,并根据哪些数据可以直接返回或从差异编译。
想法?
我相信其他人已经解决了这个问题,我很想知道有什么想法和实现。显然,有完整的版本控制系统,例如 Git、Mercurial 和 Subversion 以及 CVS - 但这些系统对于预期目的来说都有些矫枉过正,无法在 Google App Engine 上运行。
最佳答案
一些想法:
您需要一个单调递增的版本 ID,这样您就可以对版本实体进行范围查询。这可能意味着您希望所有历史数据都在与文档相同的实体组中,并在文档实体或同一组中的单独实体中保留最新版本 ID。如果您想要一个系统范围内单调递增的 ID(例如关联或排序对不同组中的多个实体所做的更改),您将需要研究分片计数器和跨组事务。
如果空间足以让您担心存储差异,我不明白您为什么要通过后台作业将完整版本缩减为差异,而不仅仅是在更新时。如果空间不是一个大问题并且一个主要特征是能够区分两个任意版本,那么存储完整数据可能更容易,因此差异的成本与中间版本的数量不成正比(或所有版本,如果您的差异在历史版本之间)。假设您不想对过去版本的属性执行查询,您可以通过以紧凑形式序列化旧实体并将其存储在非索引 blob 属性中来节省空间。 (我假设这就是你存储每个差异的方式,如果你使用差异?)你也可以在每 n 次修订的里程碑处保留完整文档,因此两个历史版本之间的差异最多需要 2n 个版本来计算。
根据您的描述,您似乎更希望 MyDoc 成为对 Version 实体的引用,该实体将包含最重要的数据。也许 MyDoc 包含最重要的数据(并使用 MyDoc 键等对其属性进行索引)会更容易,并且更新仅使用以前的数据(差异或完整)创建版本。
<不要忘记容纳删除。也许 MyDoc 消失了(因此它不会出现在键和属性查询中),并且父路径的最新版本包含完整的最后一个已知文档。
(这只是我的想法。我为我工作的 CMS 对此做了一些思考,但我还没有构建它。)
关于google-app-engine - ndb/Google App Engine 上的简单版本/历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10618854/