为什么在给定键下有单个文档的情况下,此映射会减少查询失败



我有一个名为inbound_pos的集合,它的文档有一个称为lines的键。示例如下:

{
   "_id": ObjectId("537e16cf8be10a5e7e000008"),
   "cdt": ISODate("2014-05-22T15:25:03.379Z"),
   "comments": [
     [
    ] 
  ],
   "cust_shipto_id": "103",
   "doc_dt": "20140522",
   "isa_control_id": "000030456",
   "kind": "edi",
   "lines": [
     {
       "linenumber": "1",
       "net_qty": NumberInt(10),
       "uom": "EA",
       "unitcost": 10.04,
       "v_nmbr": "005-2964",
       "tm_desc": "NA" 
    },
     {
       "linenumber": "2",
       "net_qty": NumberInt(10),
       "uom": "EA",
       "unitcost": 13.59,
       "v_nmbr": "005-2966",
       "tm_desc": "NA" 
    },
     {
       "linenumber": "3",
       "net_qty": NumberInt(6),
       "uom": "BX",
       "unitcost": 18.36,
       "v_nmbr": "2201254",
       "tm_desc": "LANTISEPTIC" 
    } 
  ]
}

在组成lines阵列的每个对象中,v_nmbrnet_qtyunitcost键分别指示正在购买的特定物品、该物品的购买数量和该物品的单价。

我想做的是获得集合中所有文档中每个v_nmbr花费的总金额。地图缩减查询如下:

db.inbound_pos.mapReduce(function() {
    for (var i=0; i<this.lines.length; i++) {
      emit(this.lines[i].v_nmbr, this.lines[i])
    }
}, function(key, values) {
    var totalExpenses = 0;
    for (var i=0; i<values.length; i++) {
      totalExpenses += values[i].unitcost * values[i].net_qty
    }
    return totalExpenses
}, {
    out: "total_expenses_per_item"
})

此查询为已多次购买的所有项目正确生成总额,但对于只购买过一次的项目则失败。

以下是一些输出示例:

成功(物品购买20次)

{
   "_id": "005-BUHW2076HRF",
   "value": 2366.4 
}

(物品已购买2次):

{
   "_id": "P54072",
   "value": 29.13 
}

失败(物品只购买过一次):

{
   "_id": "OTC11780",
   "value": {
     "linenumber": "1",
     "v_nmbr": "OTC11780",
     "net_qty": NumberInt(5),
     "unitcost": 13.68,
     "uom": "BT",
     "tm_desc": "VITAMIN E 1000 IU SOFTGEL 100/BTL" 
  } 
}

如果您有时间,我们将非常感谢您的帮助和解释。

试试这个:

db.inbound_pos.mapReduce(function() {
    for (var i=0; i<this.lines.length; i++) {
        emit(this.lines[i].v_nmbr, this.lines[i])
    }
}, function(key, values) {
    var totalExpenses = 0;
    for (var i=0; i<values.length; i++) {
        totalExpenses += values[i].unitcost * values[i].net_qty
    }
    return totalExpenses
}, {
    finalize: function(key,reducedValue) {
        if (typeof reducedValue.linenumber != 'undefined') {
            return reducedValue.unitcost;
        } else {
            return reducedValue;
        }
    },
    out: "total_expenses_per_item"
});

你的失败的原因是,如果只有一个值,map reduce不会进入reduce阶段,在这种情况下,你可以使用finalize函数只返回你想要的值。

根据文档:MongoDB不会为只有一个值的键调用reduce函数。它只是返回映射值作为结果。

但MongoDB无论如何都会为单个映射值调用finalize函数,所以您可以在那里修改结果。

最好的解决方案是遵循以下规则:reduce函数的返回对象的类型必须与map函数发出的值的类型相同。

在你的情况下,我会这样做地图减少:

db.inbound_pos.mapReduce(function() {
    for (var i=0; i<this.lines.length; i++) {
      emit(this.lines[i].v_nmbr, this.lines[i].unitcost * this.lines[i].net_qty)
    }
}, function(key, values) {
    var totalExpenses = 0;
    for (var i=0; i<values.length; i++) {
      totalExpenses += values[i]
    }
    return totalExpenses
}, {
    out: "total_expenses_per_item"
})

相关内容

  • 没有找到相关文章

最新更新