MongoDB查询中的Map Reduce技术

6
我有一个非常大的MongoDB数据库,需要通过运行Map Reduce查询来提取统计数据。
现在的问题是,我需要缩小查询范围,例如使用status:'drafted"代替使用整个集合。
以下是我的Map/Reduce代码(我正在使用Codeigniter):
我尝试遵循此查询中的最后一步,但无法获得结果,因此我认为我的语法添加错误:http://cookbook.mongodb.org/patterns/unique_items_map_reduce/
$map = new MongoCode ("function() {

                day = Date.UTC(this.created_at.getFullYear(), this.created_at.getMonth(), this.created_at.getDate());

                emit ({day: day, _id: this._id}, {created_at: this.created_at, count: 1});

            }");

            $reduce = new MongoCode ("function( key , values ) {

                var count = 0;

                values.forEach (function(v) {

                    count += v['count'];

                });

                return {count: count};

            }");

            $outer = $this->cimongo->command (array (

                "mapreduce" => "documents",   

                "map"       => $map,   

                "reduce"    => $reduce,  

                "out"       => "stats_results"

            ));


            $map = new MongoCode ("function() {

                emit(this['_id']['day'], {count: 1});

            }");

            $reduce = new MongoCode ("function( key , values ) {

                var count = 0;

                values.forEach (function(v) {

                    count += v['count'];

                });

                return {count: count};

            }");

            $outer = $this->cimongo->command (array (

                "mapreduce" => "stats_results",   

                "map"       => $map,   

                "reduce"    => $reduce,   

                "out"       => "stats_results_unique"

            ));

“使用状态 'drafted'”是什么意思?您想避免映射整个表格,还是只需发出具有该状态的键即可?我猜您想根据状态字段有条件地发出结果。 - evnu
1个回答

13

关于你的问题有两点需要注意:

1)烹饪书中的示例可能对你要实现的内容有些过于复杂。这里有一个更简单的示例:

如果给出像这样的文档结构:

{
    "url" : "http://example.com/page8580.html",
    "user_id" : "Jonathan.Clark",
    "date" : ISODate("2012-06-11T10:59:36.271Z")
}

这里有一段示例 JavaScript 代码,可以运行一个 map/reduce 作业,以计算每个不同 URL 的访问次数。

// Map function:

map = function() {
  emit({ url: this.url }, {count: 1});
}

// Reduce function:

reduce = function(key, values) {
    var count = 0;

    values.forEach(
    function(val) { count += val['count']; }
    );

    return {count: count};
};

// Run the Map/Reduce function across the 'pageviews' collection:
// Note that MongoDB will store the results in the 'pages_per_day'
//   collection because the 'out' parameter is present

 db.pageviews.mapReduce( 
    map,        // pass in the 'map' function as an argument
    reduce,     // pass in the 'reduce' function as an argument
    // options
    { out: 'pages_per_day',     // output collection
      verbose: true }       // report extra statistics
);

2) 如果你只想在“pageviews”集合的子集上运行Map/Reduce函数,你可以在调用“mapReduce()”时指定一个查询来限制“map()”函数操作的文档数量:

// Run the Map/Reduce function across the 'pageviews' collection, but 
// only report on the pages seen by "Jonathan.Clark"

 db.pageviews.mapReduce( 
    map,        // Use the same map & reduce functions as before
    reduce,     
    { out: 'pages_per_day_1user',       // output to different collection
      query:{ 'user_id': "Jonathan.Clark" }     // query descriptor
      verbose: true }       
);

请注意,如果您没有使用JavaScript,则需要将这些调用转换为您正在使用的编程语言。

3)以下是使用PHP调用Map / Reduce函数并带有查询条件的示例:

$outer = $this->cimongo->command (array (
                "mapreduce" => "pageviews",   
                "map"       => $map,   
                "reduce"    => $reduce,   
                "out"       => "pages_per_day_1user",
                "query"     => array( "user_id" => "Jonathan.Clark" )
            ));

4) 获取更多关于Map/Reduce的信息, 参见以下链接:


查询参数是我要找的,但是是否可以查询一个值的数组?例如,在find()中使用类似_id: {$in: [1,2,3,4]}的东西。 - abritez
“query”参数包含一个描述任意MongoDB查询的文档;您可以在该字段中使用任何有效的语法。 - William Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接