CouchDB过滤复制 - 删除文档

时间:2014-06-01 19:42:41

标签: couchdb replication

我正在尝试在主数据库和用户数据库之间设置过滤复制。 主服务器中的文档包含具有该文档权限的用户组列表。

{
  _id: 'one',
  groups: ['a', 'b']
}

{
  _id: 'two',
  groups: ['c', 'd']
}

我创建了一个数据库的过滤视图,该视图仅允许该组的用户获取已复制文档的副本(在此示例中硬编码' a'

{
  filters = {
    users = function(doc, req){
      return doc.groups.indexOf(req.query.group) != -1;
    }
  }
}

然后我在_replicator数据库中创建一个复制文档

{
  source: "master",
  target: "user1",
  filter: "replication/user",
  query_params: {group: "a"},
  create_target: true
}

创建此文档后,复制开始,文档“#”;从master复制到user1。文件'两个'没有复制 - 只是我想要的。

随后,用户将从组' a'分组' c'所以我创建了一个新的复制文档:

{
  source: "master",
  target: "user1",
  filter: "replication/user",
  query_params: {group: "c"},
  create_target: true
}

我想要的行为是文件'一个'要从用户数据库中删除,而对于文档'两个'被复制。因为它发生了文件' one'遗体和文件'两个'被复制了。显然,除非在源数据库中删除文档,否则复制筛选器不允许删除目标数据库。

如何处理这种情况?或者我应该考虑另一种结构吗?

2 个答案:

答案 0 :(得分:2)

据我所知,无法使用复制修改文档。但是你可以采取两种方法。

首先,您可以创建一个新数据库并复制到该数据库。例如,如果您的查询参数更改为user c而不是将其复制到user1,则创建另一个数据库some name并复制到该数据库然后删除原始数据库(或保留它以防您查询参数再次改变)。您甚至可以为源数据库使用描述性名称,如“user1_filter_a”。这是最麻烦的方式,但如果文档数量很大且重叠(如同大量用户b同时属于a和c组),并且复制器过滤器变化很快,则效率低下。

另一种方法是使用viewBulk document api。首先创建一个基于组字段emits文档的视图,如此

function map(doc){

     emit(doc.groups,doc._id);

  } 

然后使用

进行查询

startkey=["a"]&endKey=["a",{}]&include_docs=true

获取要删除的所有文档。然后迭代结果集并追加 doc._deleted=true到每个文档并向数据库发出批量请求。将删除所有文档(更多解释here)。此方法的优点是您可以保留单个数据库。

简而言之,如果您想保留单个数据库,则必须手动删除文档。但是,如果基于复制器功能对多个数据库开放,则每次过滤器更改时都可以创建一个新数据库。

答案 1 :(得分:-1)

这是一个棘手的主题。我们考虑的选项是:

  1. 当组更改复制文档并将新组保存到副本时,然后删除原始文档。删除将通过过滤器传播并从远程数据库中删除。如果从其他文档中引用了ID,则缺少修订和破损。
  2. 让用户数据库编写一个清单文件,列出数据库中的所有文档,这些文档将同步回主服务器(我们已经将其跟踪到文档传递和读取状态)。将其与预期(已过滤)的文档列表进行比较,并告诉用户数据库清除(而不是删除)应该不再存在的文档。
  3. 我找到的最佳参考资料是:http://pouchdb.com/2015/04/05/filtered-replication.html