CouchDB过滤删除文档



我试图在主数据库和用户数据库之间设置过滤复制。master中的文档包含对该文档具有访问权限的用户组列表。

{
  _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
}

一旦这个文档被创建,复制就开始了,文档'one'被从master复制到user1。文件' 2 '没有复制-这正是我想要的。

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

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

我想要的行为是将文档' 1 '从用户数据库中删除,并复制文档' 2 '。此时,文档"1"保留,而文档"2"被复制。显然,除非在源数据库中删除了文档,否则复制筛选器不允许在目标数据库中删除文档。

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

据我所知,没有办法使用复制来修改文档。但你可以采用两种方法。

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

另一种方法是使用view和Bulk文档api。首先创建一个视图,根据组字段emits文档,如下所示

function map(doc){
     emit(doc.groups,doc._id);
  } 

,然后用

查询

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

获取要删除的所有文档。然后遍历结果集并追加doc._deleted=true到每个文档,并向数据库发出批量请求。所有的文档将被删除(更多的解释在这里)。这种方法的优点是,您可以保持一个单一的数据库。

简而言之,如果你想保持一个单一的数据库,你将不得不手动删除文档。但是,如果您基于复制器功能对多个数据库开放,则只需在每次过滤器更改时创建一个新数据库即可。

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

  1. 当组更改时,复制文档并将新组保存到副本中,然后删除原始组。删除将通过过滤器传播并从远程DB中删除。缺点是如果ID是从其他文档引用的,则会丢失修订和损坏。
  2. 让用户数据库写一个清单文件,列出DB中的所有文档,并同步回主数据库(我们已经有了这个来跟踪文档交付和读取状态)。将其与预期的(过滤的)文档列表进行比较,并告诉用户数据库清除(而不是删除)不应该再存在的文档。

我找到的最好的参考是在这里:http://pouchdb.com/2015/04/05/filtered-replication.html

最新更新