Mongodb按列聚合/分组并计算特定列

时间:2013-01-25 02:14:39

标签: php mongodb aggregation-framework

我们已经设置了一个将事件写入mongo实例的基本应用程序。这是一个示例写:

"_id" : ObjectId("50fee761472870a3d610956e"),
    "user_id" : "pa-XXXXXXXXX",
    "event_id" : 1,
    "date_created" : 1337798856,
    "url" : "http://news.yahoo.com/australian-tycoon-worlds-richest-woman-103810206.html"

我们要做的是检索按URL分组的结果和某些event_id的计数。像event_grouping_a可能包含event_ids 1,6,35和event_grouping_b可能包含2,66,103。示例输出看起来像这样:

{
    url: "http://news.yahoo.com/australian-tycoon-worlds-richest-woman-103810206.html",
    event_grouping_a: 46,
    event_grouping_b: 34
},
{
    url: "http://news.yahoo.com/another-cool-story",
    event_grouping_a: 105,
    event_grouping_b: 59
}

有关如何执行此类聚合/分组的任何想法?最终的目标是在PHP中使用它,但是我在mongod控制台中做这件事并没有用。我可以通过URL对其进行分组,但我无法在单个父URL下显示这两种事件类型。它吐出这样的东西:

{
    url: "http://news.yahoo.com/australian-tycoon-worlds-richest-woman-103810206.html",
    event_grouping_a: 46
    event_grouping_b: 0
},
{
    url: "http://news.yahoo.com/australian-tycoon-worlds-richest-woman-103810206.html",
    event_grouping_a: 0
    event_grouping_b: 34
},
...

上面两个应该合并为1,但我不能为我的生活搞清楚......有什么建议吗?

1 个答案:

答案 0 :(得分:0)

我不一定喜欢使用$or语句来完成这项工作,但如果您使用的是1.3+ mongo驱动程序,则此查询应该适用于您:

$mongo = new MongoClient('dbinfo');
$collection = $mongo->selectCollection( 'dbName', 'collectionName' );

$pipeline = array(
    array( 
        '$group' => array(
            '_id' => '$url',
            'event_grouping_a' => array( 
                '$sum' => array( 
                    '$cond' => array( 
                        array( '$or' => array(
                            array( '$eq' => array( '$event_id', 1 ) ),
                            array( '$eq' => array( '$event_id', 6 ) ),
                            array( '$eq' => array( '$event_id', 35 ) )
                        ) ), 1, 0 ) 
                )   
            ),
            'event_grouping_b' => array(
                '$sum' => array(
                    '$cond' => array(
                        array( '$or' => array(
                            array( '$eq' => array( '$event_id', 2 ) ),
                            array( '$eq' => array( '$event_id', 66 ) ),
                            array( '$eq' => array( '$event_id', 103 ) )
                        ) ), 1, 0 )
                )
            )
        )
    )
);
$results = $collection->aggregate( $pipeline );

-

var_dump( $results );
array(2) { 
    ["result"]=> array(2) { 
        [0]=> array(3) { 
            ["_id"]=> string(40) "http://news.yahoo.com/another-cool-story" 
            ["event_grouping_a"]=> int(2) 
            ["event_grouping_b"]=> int(1) 
        } 
        [1]=> array(3) { 
            ["_id"]=> string(75) "http://news.yahoo.com/australian-tycoon-worlds-richest-woman-103810206.html" 
            ["event_grouping_a"]=> int(3) 
            ["event_grouping_b"]=> int(4) 
        } 
    } 
    ["ok"]=> float(1) 
}