php mongodb操作笔记

Posted on 2016-04-06 |    

前言

最近一段时间,有两个项目都需要用到php操作mongodb,操作比较频繁,记录一下操作用用到的一些方法。

连接

基础连接

1
2
3
4
5
6
$conn = new MongoClient(); #默认本地的连接
$db = $conn->db; #选择名为db的数据库
$db=$conn->selectDB("mydb"); #第二种写法
$collection = $db->collection #选择一个数据库表(集合)
$collection=$db->selectCollection('column'); #第二种写法
$collection=$conn->mydb->column; #更简洁的写法

连接

1
2
3
4
5
6
7
8
9
10
格式:new MongoClient("mongodb://用户名:密码@地址:端口/默认指定数据库",参数)
$conn = new MongoClient("mongodb://localhost");
$conn = new MongoClient("mongodb://localhost:27017");
$conn = new MongoClient("mongodb://localhost:$port"); #mongo对应端口
$conn = new Mongo("mongodb://localhost",array("replicaSet"=>true)); #负载均衡
$conn = new Mongo("mongodb://localhost",array("persist"=>"t")); #持久连接
$conn = new Mongo("mongodb://sa:123@localhost"); #带用户名密码
$conn = new Mongo("mongodb://localhost:27017,localhost:27018"); #连接多个服务器
$conn = new Mongo("mongodb:///tmp/mongo-27017.sock"); #域套接字
$conn = new Mongo("mongodb://admin:admin@localhost:27017/test",array('persist'=>'p',"replicaSet"=>true)); #完整

【注】由于我的php版本是5.4类型,mongodb是3.0.7版本,好像由于php版本太低,导致和mongdb有些不兼容,连接带有用户名密码的服务器时会报错,目前这个问题还没得到解决,只能先不加认证。


查询

基础查询

1
2
3
$data = $collection->find(array('port'=>80,'ip'=>'192.168.1.1'));
$data = $collection->find(array('port'=>array('$gt'=>80,'$lt'=>5555)));
$data = $collection->findOne();#查询一条结果
【注】
1、$gt为大于、$gte为大于等于、$lt为小于、$lte为小于等于、$ne为不等于、$exists不存在;
2、findOne()获得结果集后不能使用snapshot(),fields()等函数;

查询结果处理

查询结果返回的是MongoCursor,是mongo的游标,一般使用foreach即可读取里面的数据

1
2
3
4
5
foreach($data as $key => $value){
var_dump($key);
var_dump($value);
....
}

但是我们更习惯使用数组,就可以使用 iterator_to_array() 将游标转换成一个数组。

1
2
$cursor = $collection->find();
$array = iterator_to_array($cursor);

这样输出的则是数组类型的。

【注】使用 iterator_to_array() 会让驱动将强制载入所有搜索结果集到内存,所以对超过内存大小的结果集不要这么做

中级查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$data = $collection->find(array('port'=>80))->sort(array('timestamp'=>-1,'type'=>1)); #sort排序,-1表示降序,1表示升序 ,参数的先后影响排序
$data = $collection->find(array('port'=>80))->skip(n);#跳过n条数据
$data = $collection->find(array('port'=>80))->limit(n);#获得n条数据
$data = $collection->find()->fields(array(“user”=>true));#只显示user 列
$data = $collection->find()->fields(array(“user”=>false));#只不显示user 列

/*使用.号来查询子嵌套文档 */
{
name : "Gordon Freeman",
address : {
city : "Springfield",
state : "Florida"
}
}
$data=$collection->find(array('address.city' => 'Springfield'));

查询null和不存在的字段

1
2
3
4
5
6
7
8
//查询集合中"age"为null的值,如果此数据中没有该字段,也同样会返回数据
$data=$collection->find(array("age"=>null));

//如果要查询有数据有该字段,且值为null的,则用以下方法
$data=$collection->find(array("age"=>array('$exists'=>true,'$in'=>array(NULL))));

//查询不存在某个字段
$data=$collection->find(array("age"=>array('$exists'=>false)));

获取数量

1
2
3
4
$count = $collection->count();//得到总数
$count =$collection->find($select_query)->count();//筛选后总数
或者:
$count =$collection->count($select_query);

针对mongodb的一些格式

日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   MongoDate类型格式如下:
[timestamp] => MongoDate Object
(
[sec] => 1379495520 #表当前时间
[usec] => 0 #时间精确到微秒
)
$timestamp = date("Y-m-d H:i", $start->sec); #print 2016-4-7 16:00

/*查询某个时间段内的数据*/
$start = new MongoDate($startRaw); #创建MongoDate类型,$startRaw可为时间戳类型
如:
$start = new MongoDate(strtotime('2016-4-7 12:00:00'));
$end = new MongoDate(strtotime('2016-4-8 12:00:00'));
$time=$collection->find(array('timestamp'=>array('$gt'=>$start,'$lte'=>$end)))

/*查询一星期内的数据*/
$lastweek = new MongoDate(strtotime('-1 week'));
$data = $collection->find(array('timestamp' => array('$gt' => $lastweek)));

id

1
2
3
4
5
/*使用下面的方法来匹配{"_id":ObjectId("56df8bbed7bc8d047cc7dfa7")},查询、更新也一样
$id = new MongoId("56df8bbed7bc8d047cc7dfa7");
$data = $collection->find(array('_id'=>(object)$id));
或者
$data = $collection->find(array('_id'=>$id));

高级查询$where

如果普通的一些查询手段无法满足的时候,就可以使用$where,下面是一个小栗子

1
2
3
4
5
//返回数据中author字段值为‘bob’或pageViews字段值为5的数据,返回true表示这个数据符合筛选条件
$js = "function() {
return this.author == 'bob' || this.pageViews == 5;
}";
$cursor = $collection->find(array('$where' => $js));

【注】$where的值通常是一个函数,函数里的语法使用的js语言

插入

1
2
3
4
5
6
7
8
9
$m = new MongoClient();    // 连接到mongodb
$db = $m->test; // 选择一个数据库
$collection = $db->testcollection; // 选择集合
$document = array(
"title" => "MongoDB",
"description" => "database"
);
$collection->insert($document);
echo "数据插入成功";

更新

1
2
3
4
5
6
$m = new MongoClient();    // 连接到mongodb
$db = $m->test; // 选择一个数据库
$collection = $db->testcollection; // 选择集合
// 更新文档
$collection->update(array("title"=>"MongoDB"), array('$set'=>array("title"=>"MongoDB 教程")));
在update里的第一个选项代表筛选’title‘为‘MongoDB’的数据 将‘title‘更新为’MongoDB教程‘;

删除

1
2
$collection->remove(array("title"=>"MongoDB 教程"), array("justOne" => true));
//remove中的代表的是筛选条件

mongodb的管道

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

聚合框架中常用的有以下几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。

其中还有一些表达式操作:

Name Description
$add
$devide
$mod
$multiply
$subtract

php使用aggregate小栗子:

1
2
3
4
5
6
7
8
9
10
   $m = new MongoClient();
$db = $m->table;
$c=$db->collection;
$ops=array(
array('$match'=>array("time"=>array('$gt'=>$start,'$lt'=>$end))),
array('$project'=>array("time"=>1,"honeypot"=>1,"_id"=>0)),
array('$group'=>array("count"=>array('$sum'=>1))),
array('$sort'=>array("count"=>1))
);//注意所有管道操作符在php里只能用单引号
$results=$c->aggregate($ops);

mongodb的模糊查询

mongodb的模糊查询主要采用正则匹配,正则和javascript的正则规则相同。

不细讲,直接放一小栗子自用。

1
$this->mongo_db->where(array('aaa' => array('$regex'=>new MongoRegex("/\.$data$/i"))))->get('bbb');