【问题标题】:MongoDB mapreduce missing data with 'null' in returnMongoDB mapreduce 缺少的数据,返回 'null'
【发布时间】:2012-09-27 05:08: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 } ]

...那么数据是否在某个地方丢失了?

【问题讨论】:

    标签: mongodb mapreduce


    【解决方案1】:

    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】:

    尝试在临时集合中而不是在内存中输出 map reduce 数据。可能就是这个原因。来自Mongo Docs

    { inline : 1} - 使用此选项,不会创建任何集合,并且 整个 map-reduce 操作将在 RAM 中进行。还有,结果 map-reduce 的一部分将在结果对象中返回。注意 只有当结果集适合 16MB 时,此选项才可能 单个文档的限制。在 v2.0 中,这是您唯一可用的 辅助副本集上的选项。

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

    【讨论】:

    • 好建议,我刚刚尝试过,但仍然收到截断的数据。截断的集合将“null”作为度量和日期数组的第一个值,我想知道这是否是一个线索。
    • 哦,4个端口的查询输出只有6k,所以我并没有真正接近16mb的限制。
    • 哦,那你能把数据的 mongodump 粘贴到 pastebin 或类似的东西上。
    • 这绝对是一个线索——看我的回答——你的 map 和 reduce 格式不一致。数据限制与您的问题无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 2019-10-14
    • 2013-03-24
    • 2017-04-15
    • 2016-10-24
    • 1970-01-01
    相关资源
    最近更新 更多