尝试获取MongoDB字段中每个单词的计数是MapReduce的工作



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

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?这是地图缩减的错误用法吗?也许另一种方法可以做到这一点?(也许只是循环并更新插入到另一个集合中?

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

下面的编辑 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) {
有一个

错误{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;
}, {});

现场示例

_.reduce_.map_.isNaN_.flatten

相关内容

  • 没有找到相关文章

最新更新