PHP+MongoDB组合来做访问统计
时间:2010-07-25
来源:互联网
今天好不容易休息一天,想到前几天看到的mongodb。。就来玩一玩啊。
MongoDB是一款现在非常流行的NoSql引擎。我看上的原因有两点。
1、完美支持php。非常丰富的接口。
2、高并发的插入和写入对比mysql有极大的优势。我测试过。搜索平均是2.5倍。插入和update是10倍左右。数据就不贴上来了。
但也有很多限制。32位系统,单文件大小不能超过2G。。。插入数据的时候比较依赖内存,内存太小得把虚拟内存搞大点或者完全删除掉虚拟内存的限制
安装、介绍以及手册:www.mongodb.com 资源非常丰富。
上代码
- class MDBBrowser{
- //链接
- private $connect;
-
- private $db = null;
- protected $table_name = "statistic";
- protected $collection = "browser";
- protected $memStorage = null;
-
- //服务器信息
- private $config = array(
- "host" => "localhost", //服务器
- "user" => "sampeng", //用户名
- "password" => "这里是你的密码", //密码
- "unique" => false //唯一性
- );
-
- public function __construct(){
- $this->connect();
- $this->selectDB();
- if($this->config['unique']){
- //TODO增加用户唯一性
- $this->intMemStorage();
- }
- }
- /**
- * 选择数据库
- * @param $name 数据库名
- * @return 返回collection对象
- */
- public function table($name){
- $this->collection = $name;
- return $this->collection;
- }
-
- /**
- * 存储方法
- * 将appid的需要累计加1的字段自动加1
- * @param $appid appid。在命名空间下的应用id
- * @param $uid uid.做该操作的用户。这个是用来做限制判断的
- * @param $field 需要计数的count字段。比如reader。dig。follow等等
- * @param $namespace 命名空间
- */
- public function storage($appid,$uid,$field = "reader",$namespace = "default"){
- $this->insertAndUpdateTime();
-
- if(! ( $this->config['unique'] && $this->checkUnique($uid,$appid,$namespace)) ) {
- //检查该项是否存在
- $count = $this->db->count(array('ns'=>$namespace,'appid'=>$appid));
- if(0 == $count){
- $data['ns'] = $namespace;
- $data['appid'] = $appid;
- $save[$field] = 0;
- $result = $this->db->save($data,$save);
- }else{
- $data['ns'] = $namespace;
- $data['appid'] = $appid;
- $result = $this->db->update($data,array('$inc'=>array($field=>1)));
- unset($data);
- }
- }
- }
-
- /**
- * 获得命名空间下的某个资源的统计计数
- * @param $appid
- * @param $field 允许逗号分隔
- * @param $namespace
- */
- public function getCount($appid,$field = 'reader',$namespace = "default"){
- $map['ns'] = $namespace;
- $map['appid'] = $appid;
- $fields = explode(',',$field);
- $data = $this->db->findOne($map,$fields);
- array_shift($data);
- if(1 == count($fields)){
- $data = $data[$field];
- }
- return $data;
- }
-
- /**
- * 给定一个值,单位秒。检查是否超时。
- * 这个是全局的,没有做每个命名空间下的超时检查
- * @param $checkTime 单位秒
- */
- public function checkUpdateTime($checkTime = 300){
- $map['status'] = "extra";
- $data = $this->db->findOne($map,array('insertTime','updateTime'));
- return $data['updateTime'] - $data['insertTime'] >= $checkTime;
- }
-
- /**
- * 将指定命名空间的所有数据弹出来。返回数组。
- * 此操作将更新初始存储的insertTime和updateTime
- *
- * @param $namespace stirng|false false时是所有的数据
- * @param $remove false|true true时所有历史数据
- */
- public function popNsData($namespace,$remove = false){
-
- if(!$namespace){
- //所有ns下的统计数据都取出来
- $map['status']['$ne'] ='extra';
- }else{
- //只取一部分
- $map['ns'] = $namespace;
- }
- $data = $this->db->find($map);
- $result = array();
- while($data->hasNext()){
- $data->next();
- $tempData = $data->current();
- $appId = $tempData['appid'];
- unset($tempData['_id']);
- $result[$tempData['ns']][$appId] = $tempData;
- }
- if(!empty($result)){
- if($remove){
- $this->db->remove($map);
- }
- //修改更新时间
- $statusWhere['status'] = "extra";
-
- $time = time();
- $statusSave['insertTime'] = $time;
- $statusSave['updateTime'] = $time;
- $this->db->update($statusWhere,$statusSave);
- }
- return $result;
- }
-
- protected function connect(){
- $config = $this->config;
- $this->connect = new Mongo("mongodb://{$config['user']}:{$config['password']}@{$config['host']}");
- return $this;
- }
-
- protected function selectDB(){
- $database = $this->connect->selectDB($this->table_name);
- $this->db = $database->selectCollection($this->collection);
- return $this->db;
- }
-
- protected function insertAndUpdateTime(){
- $time = time();
- $count = $this->db->count();
- //判断是否有数据
- if(0 == $count){
- $data['status'] = "extra";
- $data['insertTime'] = $time;
- $data['updateTime'] = $time;
- $this->db->insert($data);
- }else{
- $where['status'] = "extra";
- $save['$set']['updateTime'] = $time;
- $this->db->update($where,$save);
- }
- }
-
- }
我的存储结构是这样的
{
"_id": "4c4be8437f8b9a1b36000000",
"appid": 1,
"ns": "default",
"reader": 15
}
{
"_id": "4c4bd4197f8b9a9832000000",
"insertTime": 1280042037,
"updateTime": 1280042037
}
我想的是还可以这样
{
"_id":XXX
"ns":"default”,
"info1":
{
appid:XX,
reader:XXX
}
}
就是一个namespace就只用一个数据集完全存储。。查询倒是可以。。只是我觉得这样比较麻烦。扩展也不方便。。还是用平铺的方式存储就够了。。过多的设计就是过度设计- -
比如这个帖子的浏览数就可以这样增加
$a = new MDBBrowser();
$a->storage(1,2,'reader','bbs');
支持和反对的ajax接受方这样处理
$a = new MDBBrowser();
$a->storage(1,2,'dig','bbs');
等等等等。。。
作者: 某个人 发布时间: 2010-07-25
自己先把沙发拿了。。。代码格式化怎么变这鬼样了?
作者: 某个人 发布时间: 2010-07-25
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28