MongoDB,PHP每天获得独特的访问者

时间:2013-09-17 20:42:56

标签: php mongodb mapreduce distinct

我正在使用PHP和MongoDB创建一些分析脚本,我有点卡住了。我想在一定的时间内获得每天独特的访客数量。

{
   "_id": ObjectId("523768039b7e7a1505000000"),
   "ipAddress": "127.0.0.1",
   "pageId": ObjectId("522f80f59b7e7a0f2b000000"),
   "uniqueVisitorId": "0445905a-4015-4b70-a8ef-b339ab7836f1",
   "recordedTime": ISODate("2013-09-16T20:20:19.0Z") 
}

要过滤的字段是uniqueVisitorId和recordedTime。

我在PHP中创建了一个初始化的数据库对象,它在构造对象时使我成为数据库连接,然后我使用在对象构造上创建的数据库连接将MongoDB php函数简单地映射到公共函数。

无论如何,到目前为止,我每天都会得到访客人数:

public function GetUniqueVisitorsDiagram() {
    // MAP
    $map = new MongoCode('function() {
        day = new Date(Date.UTC(this.recordedTime.getFullYear(), this.recordedTime.getMonth(), this.recordedTime.getDate()));
        emit({day: day, uniqueVisitorId:this.uniqueVisitorId},{count:1});
    }');
    // REDUCE
    $reduce = new MongoCode("function(key, values) {
            var count = 0;
            values.forEach(function(v) {
                count += v['count'];
            });
            return {count: count};
        }");
    // STATS
    $stats = $this->database->Command(array(
        'mapreduce' => 'statistics',
        'map' => $map,
        'reduce' => $reduce,
        "query" => array(
            "recordedTime" =>
                array(
                    '$gte' => $this->startDate,
                    '$lte' => $this->endDate
                )
            ),
            "out" => array(
                "inline" => 1
            )
        ));
    return $stats;          
}

如何正确过滤此数据以获取唯一身份访问者?或者更好地使用聚合,如果是这样,你可以如此友好地帮助我使用代码片段吗?

2 个答案:

答案 0 :(得分:4)

聚合框架中的$ group运算符专为此用例而设计,可能会快10到100倍。在此处阅读群组运营商:http://docs.mongodb.org/manual/reference/aggregation/group/

这里的php驱动程序实现:http://php.net/manual/en/mongocollection.aggregate.php

您可以将$ group运算符与其他运算符组合以进一步限制聚合。你可能最好自己阅读一下框架,以便更好地了解发生了什么,所以我不会为你发布一个完整的例子。

答案 1 :(得分:1)

    $m=new MongoClient();
    $db=$m->super_test;
    $db->gjgjgjg->insert(array(
        "ipAddress" => "127.0.0.1",
        "pageId" => new MongoId("522f80f59b7e7a0f2b000000"),
        "uniqueVisitorId" => "0445905a-4015-4b70-a8ef-b339ab7836f1",
        "recordedTime" => new MongoDate(strtotime("2013-09-16T20:20:19.0Z"))
    ));
    var_dump($db->gjgjgjg->find(array('recordedTime'=>array('$lte'=>new MongoDate(),'$gte'=>new MongoDate(strtotime('-1 week')))))->count()); // Prints 1
    $res=$db->gjgjgjg->aggregate(array(
            array('$match'=>array('recordedTime'=>array('$lte'=>new MongoDate(),'$gte'=>new MongoDate(strtotime('-1 week'))),'uniqueVisitorId'=>array('$ne'=>null))),
            array('$project'=>array('day'=>array('$dayOfMonth'=>'$recordedTime'),'month'=>array('$month'=>'$recordedTime'),'year'=>array('$year'=>'$recordedTime'))),
            array('$group'=>array('_id'=>array('day'=>'$day','month'=>'$month','year'=>'$year'), 'c'=>array('$sum'=>1)))
    )); 
    var_dump($res['result']);

完全回答这个问题:

    $m=new MongoClient();
    $db=$m->super_test;
    $db->gjgjgjg->insert(array(
        "ipAddress" => "127.0.0.1",
        "pageId" => new MongoId("522f80f59b7e7a0f2b000000"),
        "uniqueVisitorId" => "0445905a-4015-4b70-a8ef-b339ab7836f1",
        "recordedTime" => new MongoDate(strtotime("2013-09-16T20:20:19.0Z"))
    ));
    var_dump($db->gjgjgjg->find(array('recordedTime'=>array('$lte'=>new MongoDate(),'$gte'=>new MongoDate(strtotime('-1 week')))))->count()); // Prints 1
    $res=$db->gjgjgjg->aggregate(array(
            array('$match'=>array('recordedTime'=>array('$lte'=>new MongoDate(),'$gte'=>new MongoDate(strtotime('-1 week'))),'uniqueVisitorId'=>array('$ne'=>null))),
            array('$project'=>array('day'=>array('$dayOfMonth'=>'$recordedTime'),'month'=>array('$month'=>'$recordedTime'),'year'=>array('$year'=>'$recordedTime'))),
            array('$group'=>array('_id'=>array('day'=>'$day','month'=>'$month','year'=>'$year','v'=>'$uniqueVisitorId'), 'c'=>array('$sum'=>1))),
            array('$group'=>array('_id'=>array('day'=>'$_id.day','month'=>'$_id.month','year'=>'$_id.year'),'c'=>array('$sum'=>1)))
    )); 
    var_dump($res['result']);

接近这一点的是我所相信的。

它会重新编制一组文件,其中_id作为日期,然后当天唯一访问者的数量不受id的限制,它只会检测id是否存在。

由于您每天都需要它,您实际上可以只为$dayOfYear的一个字段交换数据部分。