【问题标题】:Trying to get a count of each word in a MongoDB field is this a job for MapReduce?尝试计算 MongoDB 字段中每个单词的数量是 MapReduce 的工作吗?
【发布时间】:2011-08-31 13:52:45
【问题描述】:

我有一个集合,里面有一堆身体帖子。例如:

posts = { { id: 0, body: "foo bar baz", otherstuff: {...} },
          { id: 1, body: "baz bar oof", otherstuff: {...} },
          { id: 2, body: "baz foo oof", otherstuff: {...} }
        };

我想弄清楚如何遍历集合中的每个文档并计算每个帖子正文中每个单词的计数。

post_word_frequency = { { foo: 2 },
                        { bar: 2 },
                        { baz: 3 },
                        { oof: 2 },
                      };

我从未使用过 MapReduce,而且我对 mongo 还是很陌生,但我正在查看 http://cookbook.mongodb.org/patterns/unique_items_map_reduce/ 上的文档

map = function() {
    words = this.body.split(' ');
    for (i in words) {
       emit({ words[i] }, {count: 1});   
    }
};

reduce = function(key, values) {
     var count = 0;
     values.forEach(function(v) {
          count += v['count'];
     });
     return {count: count};
};

db.posts.mapReduce(map, reduce, {out: post_word_frequency});

作为一个额外的困难,我在 node.js 中做这件事(使用 node-mongo-native,但如果有更简单的方法,我愿意切换到做 reduce 查询)。

    var db = new Db('mydb', new Server('localhost', 27017, {}), {native_parser:false});
    db.open(function(err, db){
            db.collection('posts', function(err, col) {
                db.col.mapReduce(map, reduce, {out: post_word_frequency});
            });
    });

到目前为止,我在那个节点告诉我 ReferenceError: post_word_frequency is not defined 时遇到了困难(我尝试在 shell 中创建它,但这仍然没有帮助)。

那么有人用 node.js 做过 mapreduce 吗?这是对 map reduce 的错误使用吗?也许另一种方式来做到这一点? (也许只是循环并插入到另一个集合中?)

感谢您的任何反馈和建议! :)

编辑下面的 Ryanos 是正确的(谢谢!)我基于 MongoDB 的解决方案缺少的一件事是找到集合并将其转换为数组。

 db.open(function(err, db){
    db.collection('posts', function(err, col) {
            col.find({}).toArray(function(err, posts){    // this line creates the 'posts' array as needed by the MAPreduce functions.
                    var words= _.flatten(_.map(posts, function(val) {

【问题讨论】:

    标签: mongodb node.js mapreduce


    【解决方案1】:

    {out: post_word_frequency} 有一个错误,也许你想要{out: "post_word_frequency"},但如果没有这个out 变量,它应该可以工作。

    使用underscore 就可以轻松搞定。

    /*
      [{"word": "foo", "count": 1}, ...]
    */
    var words = _.flatten(_.map(posts, function(val) {
        return _.map(val.body.split(" "), function(val) {
            return {"word": val, "count": 1};
        });
    }));
    
    /*
      {
        "foo": n, ...
      }
    */
    var count = _.reduce(words, function(memo, val) {
        if (_.isNaN(++memo[val.word])) {
            memo[val.word] = 1;
        }
        return memo;
    }, {});
    

    Live Example

    _.reduce_.map_.isNaN_.flatten

    【讨论】:

    • 这太棒了!谢谢。我下班回家后会检查答案,如果它成功了,我会告诉你。没见过下划线,能不能在node.js中加载?
    • @AlexC just npm install underscore && var _ = require("underscore");
    • 太棒了!它在您的示例中肯定有效 - 我仍在尝试收集 mongo 位上的所有点,但我相信这很快就会到来。谢谢一吨! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多