在CouchDB视图中引用外部文档

时间:2014-02-08 00:45:33

标签: couchdb

我正在使用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);
      }
    }
  }
}

1 个答案:

答案 0 :(得分:2)

<强>上下文

你是对的,这在CouchDB中是不可能的。 map函数的重点是它必须是幂等的,否则你会失去预先计算的索引的所有其他好处。

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

<强>解决方案

但是,您仍然可以实现最终目标,只是采用不同的方式。一些可能性......

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

  • 强力方法是使用视图配对应匹配的文档。每个文档都在不同的行上,但它们按公共字段分组。然后迭代整个索引比较对。这肯定是最快的代码,不依赖于您的应用程序或数据。

  • 实施验证功能以强制执行数据架构。请注意,这将降低您的写入吞吐量,因为每个写入的记录将从Erlang传输到JS引擎。此外,这仅适用于您担心正确形成的记录而非其精确内容的情况,而情况可能并非如此。

  • 让他们将它们放在同一个文档中,而不是创建不同文档的不同批处理作业。结构可能如下所示:{ "_id": "something meaningful", "batch_one": { ..data.. }, "batch_two": { ..data.. } }然后您的验证功能可以比较它们,或者您可以创建一个索引所有不匹配的文档的视图。所有这些都取决于您想要在管道中进行错误检查和纠正的位置。

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

希望有所帮助。

干杯。