代码之家  ›  专栏  ›  技术社区  ›  Chris Matta

MongoDB mapreduce缺少返回为“null”的数据

  •  5
  • Chris Matta  · 技术社区  · 12 年前

    所以这很奇怪。我正试图使用mapreduce在一个唯一的端口下对日期时间/度量进行分组:

    文档布局:

    {
            "_id" : ObjectId("5069d68700a2934015000000"),
            "port_name" : "CL1-A",
            "metric" : "340.0",
            "port_number" : "0",
            "datetime" : ISODate("2012-09-30T13:44:00Z"),
            "array_serial" : "12345"
    }
    

    和mapreduce函数:

    var query = {
            'array_serial' : array,
            'port_name' : { $in : ports },
            'datetime' : { $gte : from, $lte : to}
    
        }
    
        var map = function() {
            emit( { portname : this.port_name } , { datetime : this.datetime,
                                    metric : this.metric });
        }
    
        var reduce = function(key, values) {
            var res = { dates : [], metrics : [], count : 0}
    
            values.forEach(function(value){
                res.dates.push(value.datetime);
                res.metrics.push(value.metric);
                res.count++;
            })
    
            return res;
        }
    
        var command = {
            mapreduce : collection,
            map : map.toString(),
            reduce : reduce.toString(),
            query : query,
            out : { inline : 1 }
    
        }
    
        mongoose.connection.db.executeDbCommand(command, function(err, dbres){
            if(err) throw err;
            console.log(dbres.documents);
            res.json(dbres.documents[0].results);
        })
    

    如果请求了少量记录,比如5条或10条,甚至60条,我会得到我期望的所有数据。较大的查询返回截断的值。。。。


    我只是做了更多的测试,似乎它将记录输出限制在100? 这是微小的数据,当我在24小时内运行查询时,我预计会返回1440条记录。。。我刚刚跑了一个收到的80\

    这是意料之中的事吗?我没有在任何我能告诉的地方指定限制。。。


    更多数据:

    查询2012-10-01T23:00-2012-10-02T00:39(100分钟)的记录返回正确:

    [
      {
        "_id": {
          "portname": "CL1-A"
        },
        "value": {
          "dates": [
            "2012-10-01T23:00:00.000Z",
            "2012-10-01T23:01:00.000Z",
            "2012-10-01T23:02:00.000Z",
             ...cut...
            "2012-10-02T00:37:00.000Z",
            "2012-10-02T00:38:00.000Z",
            "2012-10-02T00:39:00.000Z"
          ],
          "metrics": [
            "1596.0",
            "1562.0",
            "1445.0",
            ...cut...
            "774.0",
            "493.0",
            "342.0"
          ],
          "count": 100
        }
      }
    ]
    

    …在查询2012-10-01T23:00-2012-10-02T00:39(101分钟)中再添加一分钟:

    [
      {
        "_id": {
          "portname": "CL1-A"
        },
        "value": {
          "dates": [
            null,
            "2012-10-02T00:40:00.000Z"
          ],
          "metrics": [
            null,
            "487.0"
          ],
          "count": 2
        }
      }
    ]
    

    这个 dbres.documents 对象显示正确的预期发射记录:

    [ { results: [ [Object] ],
        timeMillis: 8,
        counts: { input: 101, emit: 101, reduce: 2, output: 1 },
        ok: 1 } ]
    

    ……那么数据是不是在哪里丢失了?

    2 回复  |  直到 12 年前
        1
  •  13
  •   Asya Kamsky    12 年前

    MapReduce的第一条规则:

    您将从Reduce返回与您在Map中使用密钥发出的格式完全相同的格式。

    MapReduce的第二条规则:

    您应减少传递的值数组,以减少必要的次数。Reduce函数可能被调用多次。

    您在执行reduce时违反了这两条规则。

    您的Map函数正在发出键值对。

    key:端口名称(您应该简单地将名称作为密钥而不是文档发出)
    value:表示您需要累积的三项内容(日期、度量、计数)的文档

    请尝试以下操作:

    map = function() {  // if you want to reduce to an array you have to emit arrays
        emit ( this.port_name, { dates : [this.datetime], metrics : [this.metric], count: 1 });
    }
    
    reduce = function(key, values) {        // for each key you get an array of values
       var res = { dates: [], metrics: [], count: 0 };  // you must reduce them to one
    
       values.forEach(function(value) {
                res.dates = value.dates.concat(res.dates);
                res.metrics = value.metrics.concat(res.metrics);
                res.count += value.count;   // VERY IMPORTANT reduce result may be re-reduced
            }) 
    
            return res;
        }
    
        2
  •  1
  •   vikas    12 年前

    尝试在临时集合中而不是在内存中输出map reduce数据。也许这就是原因。从…起 Mongo Docs 以下为:

    {inline:1}-使用此选项,将不会创建任何集合,并且 整个映射缩减操作将在RAM中发生。此外,结果 的减少将在结果对象中返回。请注意 只有当结果集适合16MB时,此选项才可用 单个文档的限制。在v2.0中,这是您唯一可用的 选项。

    此外,这可能不是原因,但MongoDB在32位机器上有数据大小限制(2GB)。