我试图在主数据库和用户数据库之间设置过滤复制。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
到每个文档,并向数据库发出批量请求。所有的文档将被删除(更多的解释在这里)。这种方法的优点是,您可以保持一个单一的数据库。
简而言之,如果你想保持一个单一的数据库,你将不得不手动删除文档。但是,如果您基于复制器功能对多个数据库开放,则只需在每次过滤器更改时创建一个新数据库即可。
这是一个棘手的问题。我们考虑的选项有:
- 当组更改时,复制文档并将新组保存到副本中,然后删除原始组。删除将通过过滤器传播并从远程DB中删除。缺点是如果ID是从其他文档引用的,则会丢失修订和损坏。
- 让用户数据库写一个清单文件,列出DB中的所有文档,并同步回主数据库(我们已经有了这个来跟踪文档交付和读取状态)。将其与预期的(过滤的)文档列表进行比较,并告诉用户数据库清除(而不是删除)不应该再存在的文档。
我找到的最好的参考是在这里:http://pouchdb.com/2015/04/05/filtered-replication.html