如何在 CouchDB / Cloudant 中保存更改,以便以后对我的数据库甚至特定文档进行时间点恢复?
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
运行该函数。
那startkey
和endkey
对使用 Cloudant 如何对结果进行排序以排除除与以给定集合开头的 ID 匹配的值之外的所有内容。
更新文档
获得要恢复的版本后,获取资源的当前版本,从 loggy 数据库获取过去的版本,并使用当前版本的_rev
值将过去的版本放入资源中。巴姆,恢复。冲洗并重复进行时间点恢复。