PHP操作MongoDB学习笔记

5.3 mongo driver下载:
http://downloads.mongodb.org/mongo-latest-php5.3vc6ts.zip

把DLL复制到extension目录,然后 extension=php_mongo.dll即可

5 列出当前数据库的php mongodb程序 

1
2
3
4
5
6
7
8
9
10
11
12
   <?php
try{
$mongo = new Mongo(); //create a connection to MongoDB
$databases = $mongo->listDBs(); //List all databases
echo '<pre>';
print_r($databases);
$mongo->close();
} catch(MongoConnectionException $e) {
//handle connection error
die($e->getMessage());
}
?>

  如果是连接时用不同的端口,构造函数中用: 
$mongo = new Mongo($server=”mongodb://localhost:8888″); 
也可以指定timeout的策略; 

1
2
3
4
5
  try {
$mongo = new Mongo($options=array('timeout'=> 100))
} catch(MongoConnectionException $e) {
die("Failed to connect to database ".$e->getMessage());
}

 
6 通过PHP保存对象到mongo db中 

1
2
3
4
5
6
7
8
9
10
$connection = new Mongo();
        $database   = $connection->selectDB('myblogsite');
        $collection = $database->selectCollection('articles');
       
        $article               = array();
        $article['title']      = $_POST['title'];
        $article['content']    = $_POST['content'];
        $article['saved_at'] = new MongoDate();
       
        $collection->insert($article);

注意的是,默认不用显式create database即可,如果不存在则会自动 
新建立database,也可以: 

1
2
3
4
5
6
7
8
9
10
11
   $connection = new Mongo();
$collection = $connection->myblogsite->articles;
    mongodb的插入是异步的,如果不想异步,可以这样;
   try {
$status = $connection->insert(array('title' => 'Blog Title',
'content' => 'Blog Content'),
array('safe' => True));
echo "Insert operation complete";
} catch (MongoCursorException $e) {
die("Insert failed ".$e->getMessage());
}

则必须等插入完成后才返回给用户,继续执行下一条语句 
也可以指定timeout的策略: 
$collection->insert($document, array(‘safe’ => True, 
‘timeout’ => True)); 

7 设置自己的自增id 
 
$document = array(‘_id’ => hash(‘sha1’, $username.time()), 
将设置id为username后加上当前时间再hash. 

8 日期设置 

1
2
3
4
5
6
7
   $article['saved_at'] = new MongoDate();
   $timestamp = new MongoDate(strtotime('2011-05-21 12:00:00'));
print date('g:i a, F j', $timestamp->sec); //prints 12 pm, May 21
   $lastweek = new MongoDate(strtotime('-1 week'));  //找出一个星期以来的记录
$cursor = $articleCollection->find(array('saved_at' =>
array('$gt' => $lastweek)));

指定一定范围内的记录: 

1
2
3
4
5
   $start = new MongoDate(strtotime('2011-05-01 00:00:00'));
$end = new MongoDate(strtotime('2011-05-31 23:59:59'));
$articleCollection->find(array('saved_at'=>
array('$gte' => $start,
'$lte' => $end)));

 
9 列出某个表的所有记录 
$cursor = $collection->find(); 
<?php while ($cursor->hasNext()): 
$article = $cursor->getNext(); ?> 
<h2><?php echo $article[‘title’]; ?></h2> 
………… 

找某条记录:$article = $collection->findOne(array(‘_id’=> 
new MongoId($id))); 
查找时也可以传入多个参数: 
$moviesCollection->find(array(‘genre’ => ‘comedy’, ‘year’ => 2011)); 
if ($cursor->count() === 0)  //如果找不到 
 
如果查询多个条件: 
$collection->find(array(‘x’ => array(‘$gt’ => 100))); 
//$ is escaped within double quotes (“) 
$collection->find(array(‘x’ => array(“\$gt” => 100))); 
注意要用单引号,如果要用双引号,则要加上转义符。 

10 排序: 
$cursor->sort(array(‘saved_at’ => -1)) //按save_at字段降序排列,1为升序 
11 skip和limit: 
$cursor = $articleCollection->find(); 
//skip the first five articles in the cursor 
$cursor->skip(5); 
$cursor->limit(10);//结果集只取10条 

12 更新数据库 
$articleCollection->update(array(‘_id’ => new MongoId($id)), 
$article); 
第一个参数为指定的条件(更新条件),第二个参数为要更新的对象 
还有可选参数如下; 
$collection->update($criteria, $newobj, array(‘safe’ => True)); 
safe=true时,等到UPDATE结束才返回结果 

mongodb还支持upsert的操作:如果存在则更新,如果不存在则插入 
$users->update(array(’email’ => ‘alice@wonderland.com’), 
array(‘firstname’ => ‘Alice’, ‘lastname’=> ‘Liddell’), 
array(‘upsert’ => True)); 

这里对email为alice@wonderland.com的记录进行更新其firstname,lastname字段的内容 

13 修饰符 
比如set,只修改记录的某个部分,可以这样: 
$articles->update(array(‘_id’ => MongoId(‘4dcd2abe5981’)), 
array(‘$set’ => array(‘title’ => ‘New 
Title’))); 
使用inc: 
$articles->update(array(‘_id’ => MongoId(‘4dcd2abe5981’)), 
array(‘$set’ => array(‘content’ => ‘New Content’), 
‘$inc’ => array(‘update_count’ => 1))); 
将update_count+1 

unset: 
$articles->update(array(‘_id’ => MongoId(‘4dcd2abe5981’)), 
array(‘$unset’ => array(‘title’ => True))); 
将title field从这个document中移除 

更名rename: 
$articles->update(array(), 
array(‘$rename’ => array(‘saved_at’ => 
‘created_at’)), 
array(‘multiple’ => True)); 
将save_at更名为create_at 

 
14 删除记录 
$articleCollection->remove(array(‘_id’ => new MongoId($id))); 
$movies->remove(array(‘genre’ =>’drama’), 
array(‘justOne’ => True)); 
如果加了justOne的参数,则只删除符合条件的一条记录而已,其他不删除 

15 document的关系 
1)嵌套 
{ 
“_id” : ObjectId(“4dd491695072aefc456c9aca”), 
“username” : “alphareplicant”, 
“email” : “roybatty@androids.org”, 
“fullname” : “Roy Batty”, 
“joined_at” : ISODate(“2011-05-19T03:41:29.703Z”), 
“address” : { 
“street” : “13 Tannhauser Gate”, 
“city” : “Caprica”, 
“state” : “CC”, 
“zipcode” : 512 
}, 
} 
2)引用 
{ 
_id : ObjectId(“4dcd2abe5981aec801010000”), 
title : “The only perfect site is hind-site”, 
content : “Loren ipsum dolor sit amet…”, 
saved_at : ISODate(‘2011-05-16T18:42:57.949Z’), 
author_id : ObjectId(“4dd491695072aefc456c9aca”) 
} 

3)比如一个一对多的关系: 
比如一个文章下的评论: 
$comment = array( 
‘name’ => $_POST[‘commenter_name’], 
’email’ => $_POST[‘commenter_email’], 
‘comment’ => $_POST[‘comment’], 
‘posted_at’ => new MongoDate() 
); 
$collection->update(array(‘_id’ => new MongoId($id)), 
array(‘$push’ => array(‘comments’ => 
$comments))); 
使用的是$push的修饰符,一般来说,用内嵌的document效率比较高 
或者: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   $article = $articleCollection->findOne(array('_id' => new MongoId($id)));
$comments = (isset($article['comments'])) ? $article['comments'] : array();
$comment = array(
                    'name' => $_POST['commenter_name'],
                    'email' => $_POST['commenter_email'],
                    'comment' => $_POST['comment'],
                    'posted_at' => new MongoDate()
                );
               
array_push($comments, $comment);
$articleCollection->update(array('_id' => new MongoId($id)), array('$set' => array('comments' =>
$comments)));

使用.号来查询子嵌套文档 
{ 
name : “Gordon Freeman”, 
address : { 
city : “Springfield”, 
state : “Florida” 
} 
} 
{ 
name : “Lara Croft”, 
address : { 
city : “Miami”, 
state: “Florida” 
} 
} 
则查询address中state为florida的document: 
$users->find(array(‘address.city’ => ‘Springfield’, 
‘address.state’ => ‘Florida’)); 

//*************************

//**    连接MongoDB数据库   **//

//*************************

  //格式=>(“mongodb://用户名:密码@地址:端口/默认指定数据库”,参数)

  $conn = new Mongo();

  //可以简写为

  //$conn=new Mongo();                      #连接本地主机,默认端口.

  //$conn=new Mongo(“172.21.15.69”);                #连接远程主机

  //$conn=new Mongo(“xiaocai.loc:10086”);              #连接指定端口远程主机

  //$conn=new Mongo(“xiaocai.loc”,array(“replicaSet”=>true));    #负载均衡

  //$conn=new Mongo(“xiaocai.loc”,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_miss:miss@localhost:27017/test”,array(‘persist’=>’p’,”replicaSet”=>true));  #完整

  //详细资料:http://www.php.net/manual/en/mongo.connecting.php

//*************************

//**    选择数据库与表       **//

//*************************

  $db=$conn->mydb;                #选择mydb数据库

  //$db=$conn->selectDB(“mydb”);          #第二种写法

  $collection=$db->column;            #选择集合(选择’表’)

  //$collection=$db->selectCollection(‘column’);  #第二种写法

  //$collection=$conn->mydb->column;        #更简洁的写法

  //注意:1.数据库和集合不需要事先创建,若它们不存在则会自动创建它们.

  //    2.注意错别字,你可能会无意间的创建一个新的数据库(与原先的数据库混乱).

//查询所有数据库

$result = $conn->listDBs();

var_dump($result = $conn->listDBs(););

//*************************

//**    插入文档         **//

//*************************

  //**向集合中插入数据,返回bool判断是否插入成功. **/

  $array=array(‘column_name’=>’col’.rand(100,999),’column_exp’=>’xiaocai’);

  $result=$collection->insert($array);    #简单插入

  echo “新记录ID:”.$array[‘_id’];        #MongoDB会返回一个记录标识

  var_dump($result);              #返回:bool(true)

  //**向集合中安全插入数据,返回插入状态(数组). **/

  $array=array(‘column_name’=>’col’.rand(100,999),’column_exp’=>’xiaocai2′);

  $result=$collection->insert($array,true);  #用于等待MongoDB完成操作,以便确定是否成功.(当有大量记录插入时使用该参数会比较有用)

  echo “新记录ID:”.$array[‘_id’];        #MongoDB会返回一个记录标识

  var_dump($result);              #返回:array(3) { [“err”]=> NULL [“n”]=> int(0) [“ok”]=> float(1) }

  //**完整的写法 **/

  #insert($array,array(‘safe’=>false,’fsync’=>false,’timeout’=>10000))

  /*

   * *

   * 完整格式:insert ( array $a [, array $options = array() ] )

   *       insert(array(),array(‘safe’=>false,’fsync’=>false,’timeout’=>10000))

   *        参数:safe:默认false,是否安全写入

   *      fsync:默认false,是否强制插入到同步到磁盘

   *      timeout:超时时间(毫秒)

   *

   * 插入结果:{ “_id” : ObjectId(“4d63552ad549a02c01000009”), “column_name” : “col770”, “column_exp” : “xiaocai” }

   *       ‘_id’为主键字段,在插入是MongoDB自动添加.

   *

   *    注意:1.以下两次插入的为同一条记录(相同的_id),因为它们的值相同。

   *          $collection->insert(array(‘column_name’=>’xiaocai’));

   *          $collection->insert(array(‘column_name’=>’xiaocai’));

   *        避免

   *        $collection->insert(array(‘column_name’=>’xiaocai’),true);

   *        try {

   *            $collection->insert(array(‘column_name’=>’xiaocai’),true);

   *        }catch(MongoCursorException $e){

   *            echo “Can’t save the same person twice!n”;

   *        }

   *

   *     详细资料:http://www.php.net/manual/zh/mongocollection.insert.php

   * *

   */

//*************************

//**    更新文档         **//

//*************************

  //** 修改更新 **/

  $where=array(‘column_name’=>’col123’);

  $newdata=array(‘column_exp’=>’GGGGGGG’,’column_fid’=>444);

  $result=$collection->update($where,array(‘$set’=>$newdata));    #$set:让某节点等于给定值,类似的还有$pull $pullAll $pop $inc,在后面慢慢说明用法

  /*

   * 结果:

   * 原数据

   * {“_id”:ObjectId(“4d635ba2d549a02801000003″),”column_name”:”col123″,”column_exp”:”xiaocai”}

   * 被替换成了

   * {“_id”:ObjectId(“4d635ba2d549a02801000003″),”column_name”:”col123″,”column_exp”:”GGGGGGG”,”column_fid”:444}

   */

  //** 替换更新 **/

  $where=array(‘column_name’=>’col709’);

  $newdata=array(‘column_exp’=>’HHHHHHHHH’,’column_fid’=>123);

  $result=$collection->update($where,$newdata);

  /*

   * 结果:

   * 原数据

   * {“_id”:ObjectId(“4d635ba2d549a02801000003″),”column_name”:”col709″,”column_exp”:”xiaocai”}

   * 被替换成了

   * {“_id”:ObjectId(“4d635ba2d549a02801000003″),”column_exp”:”HHHHHHHHH”,”column_fid”:123}

   */

  //** 批量更新 **/

  $where=array(‘column_name’=>’col’);

  $newdata=array(‘column_exp’=>’multiple’,’91u’=>684435);

  $result=$collection->update($where,array(‘$set’=>$newdata),array(‘multiple’=>true));

  /**

   * 所有’column_name’=’col’都被修改

   */

  //** 自动累加 **/

  $where=array(’91u’=>684435);

  $newdata=array(‘column_exp’=>’edit’);

  $result=$collection->update($where,array(‘$set’=>$newdata,’$inc’=>array(’91u’=>-5)));

  /**

   * 更新91u=684435的数据,并且91u自减5

   */

  /** 删除节点 **/

  $where=array(‘column_name’=>’col685’);

  $result=$collection->update($where,array(‘$unset’=>’column_exp’));

  /**

   * 删除节点column_exp

   */

  /*

   * *

   * 完整格式:update(array $criteria, array $newobj [, array $options = array()  ] )

   *        注意:1.注意区分替换更新与修改更新

   *       2.注意区分数据类型如 array(’91u’=>’684435′)与array(’91u’=>684435)

   * 详细资料:http://www.mongodb.org/display/DOCS/Updating#Updating-%24bit

   * *

   */

//*************************

//**    删除文档         **//

//*************************

  /** 清空数据库 **/

  $collection->remove(array(‘column_name’=>’col399’));

  //$collection->remove();        #清空集合

  /** 删除指定MongoId **/

  $id = new MongoId(“4d638ea1d549a02801000011”);

  $collection->remove(array(‘_id’=>(object)$id));

  /*

   * *

   *  使用下面的方法来匹配{“_id”:ObjectId(“4d638ea1d549a02801000011”)},查询、更新也一样

   *   $id = new MongoId(“4d638ea1d549a02801000011”);

   *  array(‘_id’=>(object)$id)

   * *

   */

//*************************

//**    查询文档         **//

//*************************

  /** 查询文档中的记录数 **/

  echo ‘count:’.$collection->count().”

“;                      #全部

  echo ‘count:’.$collection->count(array(‘type’=>’user’)).”

“;            #可以加上条件

  echo ‘count:’.$collection->count(array(‘age’=>array(‘$gt’=>50,’$lte’=>74))).”

“;  #大于50小于等于74

  echo ‘count:’.$collection->find()->limit(5)->skip(0)->count(true).”

“;      #获得实际返回的结果数

  /**

   * 注:$gt为大于、$gte为大于等于、$lt为小于、$lte为小于等于、$ne为不等于、$exists不存在

   */

  /** 集合中所有文档 **/

  $cursor = $collection->find()->snapshot();

  foreach ($cursor as $id => $value) {

      echo “$id: “; var_dump($value); echo “

“;

  }

  /**

   * 注意:

   *    在我们做了find()操作,获得$cursor游标之后,这个游标还是动态的.

   *    换句话说,在我find()之后,到我的游标循环完成这段时间,如果再有符合条件的记录被插入到collection,那么这些记录也会被$cursor获得.

   *    如果你想在获得$cursor之后的结果集不变化,需要这样做:

   *    $cursor = $collection->find();

   *    $cursor->snapshot();

   *    详见http://www.bumao.com/index.php/2010/08/mongo_php_cursor.html

   */

  /** 查询一条数据 **/

  $cursor = $collection->findOne();

  /**

   *  注意:findOne()获得结果集后不能使用snapshot(),fields()等函数;

   */

  /** age,type 列不显示 **/

  $cursor = $collection->find()->fields(array(“age”=>false,”type”=>false));

  /** 只显示user 列 **/

  $cursor = $collection->find()->fields(array(“user”=>true));

  /**

   * 我这样写会出错:$cursor->fields(array(“age”=>true,”type”=>false));

   */

  /** (存在type,age节点) and age!=0 and age<50 **/

  $where=array(‘type’=>array(‘$exists’=>true),’age’=>array(‘$ne’=>0,’$lt’=>50,’$exists’=>true));

  $cursor = $collection->find($where);

  /** 分页获取结果集  **/

  $cursor = $collection->find()->limit(5)->skip(0);

  /** 排序  **/

  $cursor = $collection->find()->sort(array(‘age’=>-1,’type’=>1));          ##1表示降序 -1表示升序,参数的先后影响排序顺序

  /** 索引  **/

  $collection->ensureIndex(array(‘age’ => 1,’type’=>-1));                #1表示降序 -1表示升序

  $collection->ensureIndex(array(‘age’ => 1,’type’=>-1),array(‘background’=>true));  #索引的创建放在后台运行(默认是同步运行)

  $collection->ensureIndex(array(‘age’ => 1,’type’=>-1),array(‘unique’=>true));    #该索引是唯一的

  /**

   * ensureIndex (array(),array(‘name’=>’索引名称’,’background’=true,’unique’=true))

   * 详见:http://www.php.net/manual/en/mongocollection.ensureindex.php

   */

  /** 分组 **/

//  $collection->insert(array(“category” => “fruit”, “name” => “apple”));

//  $collection->insert(array(“category” => “fruit”, “name” => “peach”));

//  $collection->insert(array(“category” => “fruit”, “name” => “banana”));

//  $collection->insert(array(“category” => “veggie”, “name” => “corn”));

//  $collection->insert(array(“category” => “veggie”, “name” => “broccoli”));

//

//  $keys = array(“category” => 1);

//  $initial = array(“items” => array());

//  $reduce = “function (obj, prev) { prev.items.push(obj.name); }”;

//  $g = $collection->group($keys, $initial, $reduce);

//

//  echo json_encode($g[‘retval’]);

  //http://us.php.net/manual/en/mongocollection.group.php

  /** 取得查询结果 **/

  $cursor = $collection->find();

  $array=array();

  foreach ($cursor as $id => $value) {

     $array[]=$value;

  }

 正则匹配查询

$filter = array(

 ‘key’ => new MongoRegex(“/.*key-list-.*/i”),

);

$result = $collection->find($filter);

  $conn->close();  #关闭连接