Tag Archives: mongoDB

MongoDB::command与php

最近用mongoDB做了一个类似mysql中group by的实做:
一个collection,里面结构为:
节点 id :某物品Id
节点 date :该物品购买日期
节点 num : 该物品在该天的购买次数
里面的记录类似于:
array(’id’=>12345,’date’=>’2010-08-26′,’num’=>12)
array(’id’=>54321,’date’=>’2010-08-26′,’num’=>2)
array(’id’=>12345,’date’=>’2010-08-25′,’num’=>1)
array(’id’=>23456,’date’=>’2010-08-26′,’num’=>6)
如果我要查询每个物品一共被卖出去多少,mysql中我们会这样写:SELECT `id`,sum(num) as total FROM `tablename`  GROUP BY `id`;
那么在mongo中怎么做呢?
可以用 MongoDB::command来做:
$mdb = $mo->mydb;

$command = array(
‘group’=>array(
‘ns’ => ‘tmp_token_stat’,
‘key’=>array(’id’=>true),
‘$reduce’ => ‘function (obj, prev) { prev.sum += obj.num;}’,
‘initial’ => array(’sum’ => 0),
),
);
$rs = $mdb->command($command);
mongoDB的官方手册在:http://www.mongodb.org/display/DOCS/Aggregation
php的官方手册在:http://www.php.net/manual/en/mongodb.command.php

php与mongoDB的update操作

因为mongoDB的update方法有很多与no-sql不同的地方,所以把它单独拿出来讨论。
php的mongoDB之update方法中
只谈到了php方法和语法,
http://www.php.net/manual/en/mongocollection.update.php
但这是远远不够的。
mongoDB的官方手册中:
只提到了command方式的写法
http://www.mongodb.org/display/DOCS/Updating
没有php的具体实做方法。
在学习和实践中,要把两个手册结合起来用。
$inc
如果记录的该节点存在,让该节点的数值加N;如果该节点不存在,让该节点值等于N
设结构记录结构为 array(’a’=>1,’b’=>’t’),想让a加5,那么:
$coll->update(
array(’b’=>’t’),
array(’$inc’=>array(’a’=>5)),

)
$set
让某节点等于给定值
设结构记录结构为 array(’a’=>1,’b’=>’t’),b为加f,那么:
$coll->update(
array(’a’=>1),
array(’$set’=>array(’b’=>’f’)),

)
$unset
删除某节点
设记录结构为 array(’a’=>1,’b’=>’t’),想删除b节点,那么:
$coll->update(
array(’a’=>1),
array(’$unset’=>’b’),

)
$push
如果对应节点是个数组,就附加一个新的值上去;不存在,就创建这个数组,并附加一个值在这个数组上;如果该节点不是数组,返回错误。
设记录结构为array(’a’=>array(0=>’haha’),’b’=>1),想附加新数据到节点a,那么:
$coll->update(
array(’b’=>1),
array(’$push’=>array(’a’=>’wow’)),

)
这样,该记录就会成为:array(’a’=>array(0=>’haha’,1=>’wow’),’b’=>1)
$pushAll
与$push类似,只是会一次附加多个数值到某节点
$addToSet
如果该阶段的数组中没有某值,就添加之
设记录结构为array(’a’=>array(0=>’haha’),’b’=>1),如果想附加新的数据到该节点a,那么:
$coll->update(
array(’b’=>1),
array(’$addToSet’=>array(’a’=>’wow’)),

)
如果在a节点中已经有了wow,那么就不会再添加新的,如果没有,就会为该节点添加新的item——wow。
$pop
设该记录为 array(’a’=>array(0=>’haha’,1=>’wow’),’b’=>1)
删除某数组节点的最后一个元素:
$coll->update(
array(’b’=>1),
array(’$pop=>array(’a’=>1)),

)
删除某数组阶段的第一个元素
$coll->update(
array(’b’=>1),
array(’$pop=>array(’a’=>-1)),

)
$pull
如果该节点是个数组,那么删除其值为value的子项,如果不是数组,会返回一个错误。
设该记录为 array(’a’=>array(0=>’haha’,1=>’wow’),’b’=>1),想要删除a中value为haha的子项:
$coll->update(
array(’b’=>1),
array(’$pull=>array(’a’=>’haha’)),

)
结果为: array(’a’=>array(0=>’wow’),’b’=>1)
$pullAll
与$pull类似,只是可以删除一组符合条件的记录。

不断变化的mongoDB结果集

在前几天的一次php+mongoDB数据库实做中,遇到了一个很奇怪的问题:
有N张collection,每个collection中有Mn条记录,我先循环N,去每张collection中find()到所有记录,然后在针对每条记录做update()操作,
$mo = new Mongo();
$db =  $mo->dbname;
for($i=0;$i<100;$i++){
$coll = $db->selectCollection(’col’.$i){
$cursor = $coll->find();
while($cursor as $k=>$v){
$uid = $v['uid'];

$rs = $coll->update(array(’uid’=>$uid),array(要更新的内容));
}
}
}
但是实际上,有些记录被update的两次,百思不得其解,update()的$option换了所有方式,都无效。
后来,在Sam的帮助下,详细查了php手册的mongoDB一段,最后发现:
http://www.php.net/manual/en/mongocursor.snapshot.php
MongoCursor MongoCursor::snapshot()
Use snapshot mode for the query. Snapshot mode assures no duplicates are returned, or objects missed, which were present at both the start and end of the query’s execution (if an object is new during the query, or deleted [...]

用php实现mongoDB的基本操作

说到php连mongoDB,不得不先介绍一下php的官方手册,网址在:http://us.php.net/manual/en/book.mongo.php
在php的mongo扩展中,提供了4类接口(对象):
1,针对mongoDB连接的操作:Mongo
http://us.php.net/manual/en/class.mongo.php
2,针对mongoDB中数据库的操作:MongoDB
http://us.php.net/manual/en/class.mongodb.php
3,针对mongoDB中collection的操作:MongoCollection
http://us.php.net/manual/en/class.mongocollection.php
4,针对查询结果集的操作:MongoCursor
http://us.php.net/manual/en/class.mongocursor.php
与mongoDB建立连接:
直接实例化mongo类+创建连接:
$mo = new Mongo();//得到一个Mongo连接对象
实例化了一个Mongo类,并且与默认的localhost:27017端口的mongoDB建立连接。
如果想连接到其他的主机,可以这样写:$mongo = new Mongo(”mongodb://username:password@192.168.1.22:12345″);
另外一种方式,实例化mongo类,再手动建立连接:
$mongo = new Mongo(”mongodb://username:password@192.168.1.22:12345″,array(’connect’=>false));//初始化类
$mongo->connect();//创建连接

Mongo类中有用的一些方法:
Mongo::listDBs()
http://us.php.net/manual/en/mongo.listdbs.php
返回一个包含当前mongo服务上的库(DB)信息的数组。
$mo = new Mongo();
$dbs = $mo->listDBs();//获得一个包含db信息的数组
Mongo::selectCollection($db,$coll)
http://us.php.net/manual/en/mongo.selectcollection.php
返回一个当前连接下的某db中的collection对象。
$mo = new Mongo();
$coll = $mo->selectCollection(’db’,’mycoll’);//得到一个collection对象

选择想要的数据库(Mongo类):
一种方式:
http://us.php.net/manual/en/mongo.get.php
$mongo = new Mongo();

$db = $mongo->foo;//得到一个MongoDB对象

另一种方式:
http://us.php.net/manual/en/mongo.selectdb.php
$mongo = new Mongo();

$db = $mongo->selectDB(’foo’);//得到一个MongoDB对象
MongoDB中有用的函数:
创建一个MongoDB对象
http://us.php.net/manual/en/mongodb.construct.php
$mo = new Mongo();
$db = new MongoDB($mo,’dbname’);//通过创建方式获得一个MongoDB对象
删除当前DB
http://us.php.net/manual/en/mongodb.drop.php
$db = $mo->dbname;
$db->drop();
获得当前数据库名
http://us.php.net/manual/en/mongodb.–tostring.php
$db = $mo->dbname;
$db->_tostring();
选择想要的collection:
A:
$mo = new Mongo();
$coll = $mo->dbname->collname;//获得一个collection对象
B:
$db = $mo->selectDB(’dbname’);
$coll = $db->collname;
C:
$db = $mo->dbname;
$coll = $db->selectCollectoin(’collname’);//获得一个collection对象
插入数据(MongoCollection对象):
http://us.php.net/manual/en/mongocollection.insert.php
MongoCollection::insert(array $a,array [...]

mongoDB的特性和php-mongoDB环境的搭建

mongoDB是目前比较流行的非关系型数据库(no-sql),对于网上吹嘘的性能、吞吐、并发等大家可以自己来摸索和体会,这里不复述。
说说mongoDB一些开发级的特性吧:
1,mongo没有两表连查,相比mysql就没有 left join 或者 select … from a,b这样的操作了;
2,mongo不支持事务、存储过程等,所以用mongo做安全和稳定性高的应用不太现实;
3,mongo没有建表或者维护表结构的概念:
某个库在第一次写入操作时自动创建
某个表(mysql叫做table,mongo叫做collection)在第一次写入时自动创建
同一个collection中的每条记录的结构可以完全不同
mongoDB是有索引概念的,可以建立index和Unique类型的索引
mongoDB中collection的结构:
你不能把collection惯性的想象成一个二维表(table),因为它与sql数据库中的table有很多的不同。
mongo的collection你可以想象成一个笔记本,每一页就是一条记录,而每一页上所记录的东西就是一个节点可以完全不同的数组(array)。mongoDB在系统层面为每张collection的每条记录自动创建唯一索引——_id来检索和定位记录。
以下,我总结了collection的用法,抛砖引玉:
1,名片式:
用来存储不能完全定义出结构和节点的信息。
一张collection是一个笔记本,每一页记录一个人的名片,基本上来讲名片的结构可能是:姓名,公司名,网址,电话,Email。
有些人只会有“姓名”,“公司名”,其他的项目没有,这在mysql中也好实现,没有的项目就是null么,但是还有个可能性是,有些人要有“别 名”、“手机”、“QQ号码”等,这如果在mysql中来说,就要为这张表添加字段才可以,如果这些属性一再多下去,那就得分表连查了。而在mongo 中,只需要在insert或者update的时候为对应记录增加节点就可以了,也就是说可能A的那一页有“姓名”,“公司名”,而B的那一页可能是“姓 名”“公司名”“年龄”“QQ号”“出生地”…
这样一来,将同一类型的数据都放在了一个collection但有保持了每个个体内容的弹性。
2,菜单式:
这种方式比较适合存储配置性的信息。
请抬头看一下你目前浏览器的菜单:我用的是firefox浏览器,现在的菜单是:文件、编辑、查看、历史、书签、工具、帮助。
其中,“查看”的子菜单是:工具栏(含菜单栏、导航工具栏、书签工具栏…),状态栏,侧栏(含历史、书签)…
每个菜单项都还有自己的子项、子子项,但是他们之间又没有一致性。
我们可以用collection的每一条记录存储一个菜单项的全部内容,而我想操作“文件”的内容的时候,可以直接选择type为“文件”的记录来操作。
3,表格式:
这种方式和传统的mysql表很类似,用来存储完整性强,查询和排序条件较多的记录。
mongoDB的介绍
官方网站:http://www.mongodb.org/
官方开发者手册:http://www.mongodb.org/display/DOCS/Developer+Zone
官方管理员手册:http://www.mongodb.org/display/DOCS/Admin+Zone
官方中文手册:http://www.mongodb.org/display/DOCSCN/Home (不够及时)
什么是mongodb:http://baike.baidu.com/view/3385614.htm (百度百科)
mongoDB的安装(win)
下载想要安装的mongoDB的对应win版本:
http://www.mongodb.org/downloads
mongoDB在win下算是个绿色软件,不用一下一下的点Next,下载对应版本后:
1,将内容解压到你想要放置的对应目录,如:d:\mongodb\
2,建立一个目录,用来放数据,如d:\mongodata\
3,将mongoDB安装为windows服务:
cmd下   d:\mongodb\bin\mongod.exe –dbpath=d:\mongodata –install
之后你就可以在“服务”里面找到mongodb,关闭或者启动它。
可用mongod -help查看配置参数
官方说明书:http://www.mongodb.org/display/DOCS/Quickstart+Windows
让php支持mongoDB
php连接mongodb是个很简单的事情,官方文档在:http://www.mongodb.org/display/DOCS/PHP+Language+Center
1,下载对应的库文件
http://github.com/mongodb/mongo-php-driver/downloads 到这里选择适合你系统的dll文件(vc6是apache用户的,vc9是IIS用的)。
2,zip包中有个php_mongo.dll,放到你对应php的扩展目录,例如我的目录在D:\LAMP\php\ext
3,在你的php.ini中加入:extension=php_mongo.dll
4,重启apache,在phpinfo()中查看是否有一项关于mongo的~
如果出现关于mongo的清单,说明当前环境的php已经支持Mongodb了。如果没有,需要检查一下对应的php_mongo.dll是否与你当前的php版本对应,或者查看一下你的php扩展目录配置是否有效。

win下测试mongoDB主从服务器

win下如何安装mongoDB见我的上一篇文章
mongoDB可以安装为win的一个服务,也可以直接在cmd下启动来运行。这次的主从测试就是直接cmd方式的。
先建立两个数据库文件:
D:\db_slave (放从服务数据)
D:\db_master(放主服务数据)
开启主服务:
D:\LAMP\mongodb\bin为我的mongoDB的bin目录
D:\LAMP\mongodb\bin>mongod –port 9999 –master –dbpath D:\db_master
9999为我设置的端口号,正常情况下会出现以下字样:
Tue Jun 08 14:10:44 Mongo DB : starting : pid = 0 port = 9999 dbpath = D:\db_mas
ter master = 1 slave = 0  32-bit
** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see http://blog.mongodb.org/post/137788967/32-bit-limitations for more
Tue Jun 08 14:10:44 db version [...]

MongoDB与PHP(介绍与安装)

1,什么是mongoDB?
百度百科的链接 http://baike.baidu.com/view/3385614.htm?fr=ala0_1
mongoDB是个no-sql的数据库,有别于Sqlserver或者Mysql,你不用想着去join别的表。一个collection可以简单理解为一个json对象。
2,安装mongoDB
这个是官方的中文文档:http://www.mongodb.org/pages/viewpage.action?pageId=6750232
3,让php可访问
官方文档:http://www.mongodb.org/display/DOCS/PHP+Language+Center
win下比较简单,去
http://github.com/mongodb/mongo-php-driver/downloads
下载对应你php版本的包,之后把php_mongo.dll放到你php的ext目录,然后php.ini中加入
extension=php_mongo.dll
从新启动你的webserver就好了。
4,用php管理mongoDB
一个超级简单的,类似phpmyadmin的工具——phpmoadmin
http://www.phpmoadmin.com/ 这里下载,放到你的web路径下就ok。

MongoDb In Action

MongoDb In Action
View more presentations from fuchaoqun.