CouchDB查找配对文档并列出剩余的未配对文档

时间:2017-02-01 21:56:34

标签: javascript transactions mapreduce couchdb pouchdb

我对NoSQL比较陌生,但我一直非常享受这段旅程!然而,我发现地图减少的生活方式有点棘手!我需要一些问题的帮助!

我有一个包含两种类型文档的数据库,打开事务和关闭事务。出于复制和脱机功能的原因,我无法将数据合并到一个文档中。打开的交易文档类似于:

{
  _id: "transaction-open-randomgeneratedstring",
  type: "transactions-open",
  vehicle: "vehicle-id",
  created: "date string"
}

结账文件如下:

{
  _id: "transaction-close-randomgeneratedstring",
  type: "transactions-close",
  openid: "transaction-open-randomgeneratedstring",
  created: "date string"    
}

结算交易的randomgeneratedstring与相应的期初交易的randomgeneratedstring相匹配。

我需要map-reduce来为我提供没有相应结账交易的未结交易清单。这基本上会给我一份未完成的交易清单。

这是我迄今为止的map-reduce,但它没有完成这项工作。

{
  "map": function(doc) {
     if(doc.type == "transactions-open") {
      emit([doc._id, 0], "OPEN");
     }
     if(doc.type == "transactions-close"){
      emit([doc.openid, 1], "CLOSE");
     }
  },
  "reduce": function(keys, values, rereduce) {
    var unique_labels = {};
    var open = {};
    keys.forEach(function(label) {
     if(!unique_labels[label[0]]) {
      unique_labels[label[0]] = true;
     } else {
      open[label[0]] = true;
     }
    });
    return open;
   }
 }

我对_id命名/结构的更改持开放态度,但我无法将这两个文档合并为一个。

谢谢!

修改 根据Hod的回应,我将reduce更改为:

function(keys, values, rereducer)
{
  if(values.length == 1)
   return true;
}

这肯定是朝着正确方向迈出的一步,但不需要的事务仍然在结果集中,该值仅为null。有没有办法把它们从结果集中拿出来?

2 个答案:

答案 0 :(得分:0)

问题在于reduce函数中的keys参数。使用所有可能的键不会调用reduce阶段。它是根据不同的键调用的,并且基于您指定的group_level。

查看代码,如果未指定任何group_level,则会分别为每个文档调用reduce函数。

因为您为开放标记和关闭标记发出了开放交易文档的ID,所以如果您在第一级进行分组,则会获得打开或打开/关闭对。你一次只能减少一组有限的文档。

您可以在调用查询的逻辑中修复此问题,也可以通过发出一个键来让您立即减少整个集合。 (我想还有其他方法。想到的就是那些。)

如果使用密钥方法,则需要发出类似["transaction", doc._id, 0]的内容。然后,第一级分组将为您提供整个事务集,就像您当前的代码所期望的那样。

编辑(根据问题编辑添加信息。)

将使用您设置的任何分组调用reduce函数。它总是会返回一些东西,即使它没有发出任何结果(即为空)。

如果您不想在运行查询和处理结果的逻辑中处理该问题,则需要使用一种方法,将所有交易文档组合在一起,而不仅仅是单个文档事务。

根据您目前所做的工作,另一种方法是放弃缩减阶段,只查看查询返回的结果数量,该查询仅限于唯一的文档ID。

答案 1 :(得分:0)

正如所描述的 - 你将使用Join in SQL做什么,你可以使用CouchDB中的reduce。代码是这样的 - 未经测试:

 {
  "map": function(doc) {
     if(doc.type == "transactions-open") {
      emit([doc._id], 1);
     }
     if(doc.type == "transactions-close"){
      emit([doc.openid], -1);
     }
  },
  "reduce": "_sum";
 }

因此,我们为ID下的开放事务发出1,为相同ID下的结束发出-1。现在,当你减少时,你会得到每个ID的结果:

  • -1 =已关闭,没有打开记录(错误情况)。
  • 0 =已关闭
  • 1 =打开但尚未关闭。