不能让Map/Reduce与MongoDB一起工作


Can't get Map/Reduce to work with MongoDB

我有这样的代码:

// construct map and reduce functions
$map = new MongoCode("
    function() { ".
        "var key = {date: this.timestamp.getFullYear()+this.timestamp.getMonth()+this.timestamp.getDate()};".
        "emit(key, {count: 1});
    }"
);
$reduce = new MongoCode("
    function(k, vals) { ".
        "var sum = 0;".
        "for (var i in vals) {".
            "sum += vals[i];". 
        "}".
        "return sum;".
    "}"
);
$dates = $db->command(array(
    "mapreduce" => "items", 
    "map" => $map,
    "reduce" => $reduce,
    //"query" => array("type" => "sale"),
    "out" => array("merge" => "distinct_dates")
    )
);

但是当测试时得到这个错误:

Array ([assertion] => map invoke failed: JS Error: TypeError: this.timestamp.getFullYear is not a function) nofile_b:0 [assertionCode] => 9014 [errmsg] => db assertion failure [ok] => 0) Cron run finished.

集合中的每个对象都有一个时间戳,我想从中提取一个日期(Ymd),并将每个不同的日期放在一个新的集合中。

在MongoDB中,您不能按原样存储Date对象。你的时间戳是int类型的。我希望,如果你这样定义你的map函数,一切都会好起来的:

$map = new MongoCode("
    function(){
         var date = new Date(this.timestamp * 1000) //JS Date need milliseconds 
         var key = date.getFullYear() + date.getMonth() + date.getDate();
         emit(key, {count: 1})
    }
")

问题在于您的"timestamp"字段的类型不正确。如果您将其存储为纯字符串,如:

"timestamp" : "Wed May 05 2010 15:37:58 GMT-0400 (EDT)"

你会得到这个错误。将其更改为以下内容将使您的映射按预期工作:

new Date("Wed May 05 2010 15:37:58 GMT-0400 (EDT)")

当你看到它作为ISODate()对象存储在Mongo的输出中时,你就知道你在正确的轨道上了。