我希望创建一个系统来跟踪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?
算法概述如下:
保存
每次用户保存文档时,将所有最新数据放入新版本并指向该实例.
此时或之后的某个时间,通过旧版本并将完整保存更改为差异(以节省空间),例如diff-match-patch.我希望每小时,每天或一些设定时间可以完全保存 – 或者设定一些差异.
载入中
装载头是微不足道的.
较旧的版本将被标记为完整保存或差异,并且取决于哪些数据可以直接返回或从diff编译.
思考?
我相信其他人已经解决了这个问题,我很想知道有什么想法和实现.显然,有完整的版本控制系统,如Git,Mercurial和Subversion以及CVS – 但这些都是针对预期目的的过度杀伤,并且不适用于Google App Engine.
最佳答案 一些想法:
>您需要为版本提供单调递增的ID,因此您可以对版本实体进行范围查询.这可能意味着您将希望与文档位于同一实体组中的所有历史数据,并将最新版本ID保留在文档实体上或同一组中的单独实体中.如果您希望系统范围内单调增加ID(例如关联或订购对不同组中的多个实体所做的更改),您将需要查看分片计数器和跨组事务.
>如果空间足以让你存储差异,我不明白为什么你要将完整版本减少到后台作业的差异,而不仅仅是更新.如果空间不是一个大问题,并且主要特征是能够区分两个任意版本,那么存储完整数据可能更容易,因此差异的成本与中间版本的数量不成比例(或所有版本,如果您的差异介于历史版本之间).假设您不想对过去版本的属性执行查询,可以通过以紧凑形式序列化旧实体并将其存储在非索引blob属性中来节省空间. (我假设这是你如何存储每个差异,如果你使用差异?)你也可以在每个修订版本的里程碑保留完整的文档,所以两个历史版本之间的差异需要最多2n个版本来计算.
>从您的描述中,您可能更喜欢MyDoc作为对Version实体的引用,该实体将包含最顶层的数据.也许MyDoc更容易包含最前面的数据(并且其属性用MyDoc键索引等),并且更新只是创建带有先前数据(diff或full)的Version.
>不要忘记容纳删除.也许MyDoc消失了(因此它不会显示在键和属性查询中),并且父路径的最新版本包含完整的最后一个已知文档.
(这只是我的头脑.我为这个CMS做了一点思考,但是我还没有建立它.)