繁体   English   中英

在javascript / node.js中重现MongoDB的地图/发射功能(没有MongoDB)

[英]Reproducing MongoDB's map/emit functionality in javascript/node.js (without MongoDB)

我喜欢MongoDB提供的用于执行映射/归约任务的功能,特别是mapper函数中的emit()。 没有MongoDB的情况下,如何在javascript / node.js中重现下面显示的地图行为?

示例( 来自MongoDB Map-Reduce Docs ):

[{ cust_id: "A123", amount: 500 }, { cust_id: "A123", amount: 250 }, { cust_id: "B212", amount: 200 }] 

映射至-

[{ "A123": [500, 200] }, { "B212": 200 }]

一个使它像Mongo的一句话一样简单的库emmit()会很不错,但是本机函数也可以做到。

Array.reduce可以满足您的需求。 这是文档: https : //developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

我还建议您使用具有reduce&reduceRight的undescore.js(如第一条评论)。 http://underscorejs.org/#reduce

如果您只是想使用emit语法,那是可能的。 扫描出函数体并传入新的发射函数。

function mapReduce(docs, m, r) {
  var groups = {}
  function emit(key, value) {
    if (!groups[key]) { groups[key] = [] }
    groups[key].push(value)
  }
  var fn = m.toString()
  var body = fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
  var map = new Function('emit', body)
  docs.forEach(function (doc) {
    map.call(doc, emit)
  })
  var outs = []
  Object.keys(groups).forEach(function (key) {
    outs.push({ _id: key, value: r(key, groups[key]) })
  })
  return outs
}

编辑,忘记示例:

var docs = // from above

Array.sum = function (values) {
  return values.reduce(function (a, b) { return a + b })
}

mapReduce(docs, 
  function () {
    emit(this.cust_id, this.amount)
  },
  function (k, values) {
    return Array.sum(values)
  }
)

// [ { _id: 'A123', value: 750 }, { _id: 'B212', value: 200 } ]

我同意有很多很棒的lib方法可以做到这一点,并且使用Array方法很简单。 这是我的建议 这非常简单,仅使用forEach Array方法。 我已经完成了一个循环,但是还有许多其他方法。

最后,我没有做过减少,因为您没有要求这样做,但是我希望这会有所帮助。

function emit (key, value, data) {
    var res = {}; out = [];
    data.forEach(function (item) {
        var k = item[key];
        var v = item[value];
        if (k !== undefined && v !== undefined) {
            if (res[k] !== undefined) {
                out[res[k]][k].push(v);
            } else {
                var obj = {};
                res[k] = out.length;
                obj[k] = [v];
                out.push(obj);
            } 
        }
    });
    return out;
}

var data = [{name: 'Steve', amount: 50},{name: 'Steve', amount: 400}, {name: 'Jim', amount: 400}];

emit('name', 'amount', data)) // returns [{"Steve":[50,400]},{"Jim":[400]}]

emit('amount', 'name', data)) // returns [{"50":["Steve"]},{"400":["Steve","Jim"]}]

我使用了一个对象来存储每个唯一条目的数组索引。 有很多版本。 可能比我的要好很多,但是以为我会给你一个普通的JS版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM