2

PHP/MongoDB を使用した Map/Reduce に初めて取り組みました。MapReduce コマンドを実行するとエラーが発生します。

私のコード:

$map = "function () {".                                                                                                             
"emit(this.topic_id, {re_date:this.date_posted}); " .                                                                     
"}";

$reduce = "function (key, values) {" . 
"var result = {last_post: 0};" .                                                                                                 
"var max = ISODate('1970-01-01T00:00:00Z');" .                                                                             
"values.forEach(function (value) {" .
       "if (max == ISODate('1970-01-01T00:00:00Z')) {" .
           "max = value.re_date;}" .
      "if (max < value.re_date) {max = value.re_date;}});" .    
"result.last_post = max;" .                                                                                   
"return result;"  .                                                                                              
"}";



$mapFunc = new MongoCode($map);
$reduceFunc = new MongoCode($reduce);

$collection = new MongoCollection($db, 'posts');
$command = array(
'mapreduce' => $collection,
'map' => $mapFunc,
'reduce' => $reduceFunc,
"query" => array("topic_id" => "2116"),
"out" => array("merge" => "eventCounts"));


$threadInfo = $db->command($command);

$threadsCollection = $db->selectCollection($threadInfo['result']);

$stats = $statsCollection->find();

foreach ($stats as $stat) {
    echo $stats['_id'] .' Visited ';
    foreach ($stats['value']['types'] as $type => $times) {
        echo "Type $type $times Times, ";
    }
    foreach ($stats['value']['tags'] as $tag => $times) {
        echo "Tag $tag $times Times, ";
    }
    echo "\n";
}

コマンドを実行すると、次のエラーが返されます。

アサーション フィールド (mapreduce) の型が間違っています 3 != 2 assertionCode 13111
errmsg db アサーションの失敗
ok 0

ここの例にかなり厳密に従っているので、何が間違っているのかわかりません。任意の提案をいただければ幸いです。

4

1 に答える 1

3

mapReduce() を使用する場合、reduce() 関数の戻り値は、reduce() 関数の「values」要素で取得すると予想されるものと同じ形状である必要があることを覚えておくことが重要です。次に、emit() 関数によって放出されるものと同じ形状である必要があります。

次の形式のドキュメントを含むコレクションがあるとします。

> db.posts.count();
1000
> db.posts.findOne();
{
    "_id" : 0,
    "date_posted" : ISODate("2012-04-04T05:54:44.535Z"),
    "topic_id" : "sierra"
}

次のコードは、必要な出力を生成します。

<?php

$conn = new Mongo("localhost:$port");
$db = $conn->test;
$collection = $db->tst;

$map = new MongoCode(
    "function() { emit( this.topic_id, { last_post: this.date_posted } ); }"
);

$reduce = new MongoCode(
  "function(key, values) { ".
      "var max = ISODate('1970-01-01T00:00:00Z'); ".

      "values.forEach(function(val) { ".
          "if ( max < val.last_post ) max = val.last_post; ".
      "}); ".

      "return {last_post : max}; " .
  "}"
);


$result = $db->command( array(
    "mapreduce" => "posts",
    "map" => $map,
    "reduce" => $reduce,
    "query" => array( "topic_id" => "alpha"), 
    "out" => array( "merge" => "lastPosts")
    )
);
echo "result: "; print_r($result);

$collection = $db->lastPosts;
$cursor = $collection->find()->limit(6);

date_default_timezone_set("UTC");
foreach( $cursor as $doc ) {
    $date = date( "r", $doc['value']['last_post']->sec );
    echo $doc['_id'] . " last visited at " . $date ."\n" ;
}

?>
于 2012-07-31T22:05:39.090 に答える