[英]MongoDB, PHP getting unique visitors per day
I'm creating some analytics script using PHP and MongoDB and I am a bit stuck. 我正在使用PHP和MongoDB创建一些分析脚本,但有点卡住了。 I would like to get the unique number of visitors per day within a certain time frame. 我想在特定时间段内每天获得唯一身份的访问者。
{
"_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")
}
The field to filter on is uniqueVisitorId and recordedTime. 要过滤的字段是uniqueVisitorId和recordedTime。
I've created a database object in PHP that I initialise and it makes me a database connection when the object is constructed, then I have MongoDB php functions simply mapped to public function using the database connection created on object construction. 我已经在PHP中创建了一个初始化的数据库对象,并且在构造对象时使它与数据库建立了连接,然后使用在对象构造上创建的数据库连接将MongoDB php函数简单地映射到了公共函数。
Anyhow, so far I get the number of visitors per day with: 无论如何,到目前为止,我每天的访问人数是:
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;
}
How would I filter this data correctly to get unique visitors? 如何正确过滤此数据以获得唯一身份访问者? Or would it better to use aggregation, if so could you be so kind to help me out with a code snippet? 还是使用聚合会更好,如果可以的话,您是否愿意帮助我提供代码片段?
The $group operator in the aggregation framework was designed for exactly this use case and will likely be ~10 to 100 times faster. 聚合框架中的$ group运算符正是为此用例而设计的,可能会快10到100倍。 Read up on the group operator here: http://docs.mongodb.org/manual/reference/aggregation/group/ 在此处阅读有关组运算符的信息: http : //docs.mongodb.org/manual/reference/aggregation/group/
And the php driver implementation here: http://php.net/manual/en/mongocollection.aggregate.php 以及此处的php驱动程序实现: http : //php.net/manual/zh/mongocollection.aggregate.php
You can combine the $group operator with other operators to further limit your aggregations. 您可以将$ group运算符与其他运算符结合使用,以进一步限制聚合。 It's probably best you do some reading up on the framework yourself to better understand what's happening, so I'm not going to post a complete example for you. 最好您自己阅读一下框架,以更好地了解正在发生的事情,因此,我不会为您提供完整的示例。
$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']);
To answer the question entirely: 要完全回答这个问题:
$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']);
Something close to that is what your looking for I believe. 我相信您所寻找的是与之接近的东西。
It will reutrn a set of documents that have the _id
as the date and then the count of unique visitors for that day irresptive of the of the id, it simply detects only if the id is there. 它将删除一组以_id
为日期的文档,然后是当天唯一身份访问者的数量,而不考虑id的数量,它仅检测到id是否存在。
Since you want it per day you can actually exchange the dat parts for just one field of $dayOfYear
I reckon. 由于您每天都需要它,因此您实际上可以将dat部件$dayOfYear
我认为的$dayOfYear
一个字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.