Mongodb聚合函数用于嵌入文档的总和不起作用

时间:2013-08-06 10:11:40

标签: mongodb mongodb-php

我收到类似

的错误
Array
(
    [errmsg] => exception: the $unwind field path must be specified as a string
    [code] => 15981
    [ok] => 0
)

虽然我对给定的嵌入文档使用了以下查询(我想从我给定的表结构记录中总结rate_number)

global $DB, $mongo;
$theObjId = new MongoId($post_id);
$collection = $mongo->getCollection('mongo_hw_posts');

$rt_sum = $collection->aggregate(
    array('$unwind'=>$rate),
    array('$group'=>
        array(
            '_id' => $theObjId
        ),
        array(
            'rate_number'=>array('$sum' =>$rate.'rate_number')
        ))
);

表格结构

 {
   "_id": ObjectId("51ff3b38636e3b9803000001"),
   "class_id": NumberInt(2986),
   "created_by": NumberInt(1758),
   "created_datetime": NumberInt(1375681336),
   "deleted": NumberInt(0),
   "learn": {
     "0": {
       "user_id": NumberInt(0),
       "learn_date": NumberInt(0)
    }
  },
   "parent_id": "0",
   "post_text": "2%20C",
   "post_type": "text_comment",
   "rate": {
     "0": {
       "user_id": NumberInt(0),
       "rate_date": NumberInt(0),
       "rate_number": NumberInt(0)
    },
     "1": {
       "user_id": NumberInt(1457),
       "rate_date": NumberInt(1375764137),
       "rate_number": NumberInt(3)
    },
     "2": {
       "user_id": NumberInt(1619),
       "rate_date": NumberInt(1375764694),
       "rate_number": NumberInt(8)
    }
  },
   "serialized_data": "",
   "unique_key": "8bdddfe8137d14702b4517f7e8e88ee3",
   "user_role": "student"
}   

1 个答案:

答案 0 :(得分:5)

您的aggrgation命令有一些问题。

<强> $退绕

而不是:

array( '$unwind' => $rate ),

您需要使用:

array( '$unwind' => '$rate'),

$rate 只是一个PHP变量,而是MongoDB中的字段值表达式。

但是你也不能使用这样的$unwind,因为:

“errmsg”:“异常:$ unwind字段路径末尾的值'$ rate'必须是一个数组,但它是一个对象”,

那是因为rate是:

"rate": {
    "0": {
       "user_id": NumberInt(0),
       "rate_date": NumberInt(0),
       "rate_number": NumberInt(0)
    },
    "1": {
       "user_id": NumberInt(1457),
       "rate_date": NumberInt(1375764137),
       "rate_number": NumberInt(3)
    },
    "2": {
       "user_id": NumberInt(1619),
       "rate_date": NumberInt(1375764694),
       "rate_number": NumberInt(8)
    }
}

但它需要看起来像:

"rate": [
    {
       "user_id": NumberInt(0),
       "rate_date": NumberInt(0),
       "rate_number": NumberInt(0)
    },
    {
       "user_id": NumberInt(1457),
       "rate_date": NumberInt(1375764137),
       "rate_number": NumberInt(3)
    },
    {
       "user_id": NumberInt(1619),
       "rate_date": NumberInt(1375764694),
       "rate_number": NumberInt(8)
    }
]

否则,$unwind将无效。您需要为此更改文档。

<强> $组

您的$group也错了,而不是:

array('$group'=>
    array(
        '_id' => $theObjId
    ),
    array(
        'rate_number'=>array('$sum' =>$rate.'rate_number')
    )
)

你需要明确语法:

array('$group'=>
    array(
        '_id' => $theObjId
        'rate_number'=>array('$sum' => '$rate.rate_number')
    )
)

我不明白为什么你有:

'_id' => $theObjId

您是否只想汇总一个帖子的费率?如果是这种情况,您需要添加$match并将$theObjId更改为null,如下所示:

$rt_sum = $collection->aggregate(
    array( '$match' => array( '_id' => $theObjId ) ),
    array( '$unwind' => '$rate' ),
    array( '$group'=>
        array(
            '_id' => null,
            'rate_number' => array('$sum' => '$rate.rate_number')
        )
    )
);

完整的例子在这里:

<?php
$m = new MongoClient;

$c = $m->test->so;
$c->drop();

$post_id = "51ff3b38636e3b9803000001";

$theObjId = new MongoId($post_id);

$c->insert( array(
    "_id" => new MongoId("51ff3b38636e3b9803000001"),
    "class_id" => 2986,
    "created_by" => 1758,
    "created_datetime" => 1375681336,
    "deleted" => 0,
    "learn" => array(
        array(
            "user_id" => 0,
            "learn_date" => 0
        )
    ),
    "parent_id" => "0",
    "post_text" => "2%20C",
    "post_type" => "text_comment",
    "rate" => array(
        array(
            "user_id" => 0,
            "rate_date" => 0,
            "rate_number" => 0
        ),
        array(
            "user_id" => 1457,
            "rate_date" => 1375764137,
            "rate_number" => 3
        ),
        array(
            "user_id" => 1619,
            "rate_date" => 1375764694,
            "rate_number" => 8
        )
    ),
    "serialized_data" => "",
    "unique_key" => "8bdddfe8137d14702b4517f7e8e88ee3",
    "user_role" => "student"
) );

$rt_sum = $c->aggregate(
    array( '$match' => array( '_id' => $theObjId ) ),
    array( '$unwind' => '$rate' ),
    array( '$group'=>
        array(
            '_id' => null,
            'rate_number' => array('$sum' => '$rate.rate_number')
        )
    )
);

var_dump ($rt_sum);

输出是:

array(2) {
    'result' =>
    array(1) {
        [0] =>
        array(2) {
            '_id' => NULL
            'rate_number' => int(11)
        }
    }
    'ok' =>
    double(1)
}