我对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。有没有办法把它们从结果集中拿出来?
答案 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的结果: