2

如何在 CouchDB / Cloudant 中保存更改,以便以后对我的数据库甚至特定文档进行时间点恢复?

4

1 回答 1

1

我们正在努力使其成为一流的功能,但在我们推出之前,我们的一位客户是这样做的:

你有收藏,在这些收藏中,有资源。因此,您保留一个日志数据库,其中每个文档都有一个 ID collection-resource,因此对于名为“cars”的集合和名为“Ford”的资源,您的日志数据库中有一个名为 的文档cars-ford。该文档如下所示:

{
  versions: [...]
}

每当触及或修改该资源时,您的应用程序都会通过将新版本附加到versions字段末尾来更新日志记录文档。该版本可能如下所示:

{
  timestamp: '...', # some integer timestamp, for sorting
  doc: {...} # attributes of the document as of the save
}

我们将使用该视图返回所有文档的所有版本的列表,按每次更改发生的时间排序。

然后,这是您如何使用它进行恢复等操作:

获取资源的最新版本

获取整个文档,并获取versions字段中的最后一个元素。那是最新的版本。

查看与时间戳相关的所有版本

我们将创建一个按时间戳排序的视图。视图如下所示:

{
  map: "function(doc) {
      for(var i in doc.versions){
        emit(doc.versions[i].timestamp, doc.versions[i].doc);
      }
    }"
}

假设我们的数据库被命名loggy,我们的视图所在的设计文档被命名restore,视图本身也被命名time。然后我们将向这个 URL 发出 GET 请求:

{CLOUDANT_HOST}/loggy/_design/restore/_view/time?startkey='...'

...其中的值startkey是一些时间戳。未经修改,这将返回指定时间戳之后的每个版本。添加limit=X,您将在时间戳之后获得 X 版本。添加descending=true,您将获得时间戳之前的版本,而不是之后的版本。

查看资源的第 N 版

很像上面,但我们会稍微调整一下我们的视图:

{
  map: "function(doc){
      for(var i in doc.versions){
        emit(i, doc.versions[i].doc);
      }
    }"
}

现在我们的视图结果由索引而不是时间戳作为键控。因此,我们没有将时间戳传递给startkey,而是将 N 传递给第 N 次修订前后的版本。

获取集合或资源的修订数量

我们将使用另一个视图按集合和资源进行分组:

{
  map: "function(doc){
    // split te ID into collection and resource
    var parts = doc._id.split('-');
    // emit them as keys so we can group by them
    emit([doc.parts[0], doc.parts[1]], null);
  }",
  reduce: "_count"
}

使用查询参数group并按group_level其键对结果进行分组。因此,如果我们想要获取集合中已触及资源的事件数cars,我们将使用如下查询字符串:

?group=true&group_level=1&key="cars"

group对键相同的结果进行分组,但group_level=1表示“仅在第一个键上分组”,在我们的例子中是集合。key指定仅返回其键与给定值匹配的文档。

获取给定集合的所有资源

使用_all_docs视图,我们将使用如下查询字符串:

?reduce=false&startkey="{collection}-"&endkey="{collection}0"

还记得reduce我们函数的一部分吗?该_count值意味着“返回由map”发出的记录数。reduce=false意思是“不要那样做”。相反,仅map运行该函数。

startkeyendkey对使用 Cloudant 如何对结果进行排序以排除除与以给定集合开头的 ID 匹配的值之外的所有内容。

更新文档

获得要恢复的版本后,获取资源的当前版本,从 loggy 数据库获取过去的版本,并使用当前版本的_rev值将过去的版本放入资源中。巴姆,恢复。冲洗并重复进行时间点恢复。

于 2013-07-22T19:55:59.520 回答