在CouchDB视图中引用外部文档

在CouchDB视图中引用外部文档,couchdb,Couchdb,我正在使用JSON-RPC抓取一个90K记录数据库,并尝试进行一些基本的错误检查。首先,我想使用两种不同的设置对数据库进行两次刮取,并在第二次刮取中添加前缀。通过这种方式,我可以检查以确保这两个设置不会产生不同的记录(由于删除了更新等)。我想使用一个视图来实现比较,该视图将第一次刮取的每个文档与第二次刮取生成的孪生文档进行比较,然后发出记录名称,并在它们之间存在差异 但是,我不太清楚如何在视图中拉入另一个文档,我读过的所有内容都只讨论使用emit()函数的外部文档,现在进行比较已经太迟了。在下面

我正在使用JSON-RPC抓取一个90K记录数据库,并尝试进行一些基本的错误检查。首先,我想使用两种不同的设置对数据库进行两次刮取,并在第二次刮取中添加前缀。通过这种方式,我可以检查以确保这两个设置不会产生不同的记录(由于删除了更新等)。我想使用一个视图来实现比较,该视图将第一次刮取的每个文档与第二次刮取生成的孪生文档进行比较,然后发出记录名称,并在它们之间存在差异

但是,我不太清楚如何在视图中拉入另一个文档,我读过的所有内容都只讨论使用
emit()
函数的外部文档,现在进行比较已经太迟了。在下面的示例中,
lookup()
函数将获取引用的文档

这是不可能的吗

function(doc) {
  if(doc._id.slice(0,1)!=='$' && doc._id.slice(0,1)!== "_"){
    var otherDoc = lookup('$test" + doc._id);
    if(otherDoc){
    var keys = doc.value.keys();
    var same = true;
    keys.forEach(function(key) {
      if ((key.slice(0,1) !== '_') && (key.slice(0,1) !=='$') && (key!=='expires')) {
        if (!Object.equal(otherDoc[key], doc[key])) {
          same = false;
        }
      }
    });
      if(!same){
        emit(doc._id, 1);
      }
    }
  }
}

上下文

您是正确的,这在CouchDB中是不可能的。map函数的全部要点是它必须是幂等的,否则您将失去预先计算索引的所有其他好处

这就是为什么您不能在map函数中访问外部资源,无论它们是其他记录还是时钟。无论何时运行映射,如果将相同的记录放入其中,则必须始终获得相同的结果。因为CouchDB中的记录之间没有关系,所以不能保证这是可能的

解决方案

然而,你仍然可以实现你的最终目标,只是不同的方法。一些可能性

  • 假设每个文档中都有一些有意义的数值,您可以使用一个视图来获取所有这些值的总和,并根据导入操作对它们进行分组(
    {key:,value:}
    )。然后比较客户端或浏览器中的两个数字,看看它们是否匹配

  • 蛮力方法是使用视图来配对应该匹配的文档。每个文档位于不同的行上,但它们按公共字段分组。然后遍历整个索引,比较两个索引对。这无疑是最快的编码方式,不依赖于您的应用程序或数据

  • 实现一个验证函数,在数据上强制实施模式。请注意,这将降低您的写入吞吐量,因为每个写入的记录都将通过管道从Erlang传输到JS引擎。此外,这仅适用于担心格式正确的记录而不是其精确内容的情况,而事实可能并非如此

  • 不要让不同的批处理作业创建不同的文档,而是让它们将它们放在同一个文档中。结构可能如下所示:
    {“\u id”:“有意义的东西”,“批处理一”:{..data..},“批处理二”:{..data..}}
    然后验证函数可以对它们进行比较,或者您可以创建一个视图,对所有不匹配的文档进行索引。这一切都取决于您希望在管道中的何处执行错误检查和更正

就我个人而言,我更喜欢最后一个选项,但前提是您不打算在生产中使用数据库。也就是说,你不想在每个记录中都携带那些额外的数据

希望有帮助

干杯