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

CouchDB find paired documents and list remaining unpaired documents

我对 NoSQL 比较陌生,但我非常享受这段旅程!然而,我发现 map-reduce 的生活方式有点棘手!我需要一些帮助来解决问题![​​=16=]

我有一个数据库,其中包含两种类型的文档,打开交易和关闭交易。出于复制和离线功能的原因,我不能将数据合并到一个文档中。期初交易文件类似于:

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

这当然是朝着正确方向迈出的一步,但不需要的交易仍在结果集中,值为空。有没有办法把它们从结果集中取出来?

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

查看您的代码,如果您没有指定任何 group_level,您的 reduce 函数将分别为每个文档调用。

因为您为打开和关闭标记发出打开事务文档的 ID,如果您在第一级分组,您将得到打开或 open/close 对。您一次仍然只能减少一组有限的文档。

您可以在调用查询的逻辑中解决此问题,或者通过发出一个键让您一次减少整个集合。 (我想还有其他方法。这些是我想到的。)

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

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

无论您设置什么分组,都会调用 reduce 函数。它总是会 return 某些东西,即使它只是没有发出结果(即 null)。

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

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

如前所述 - 您将在 SQL 中使用 Join 执行的操作与在 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 = 打开但尚未关闭。