在之前的《MongoDB分布式部署》中已经提到,同一组数据库服务器上的数据是支持复制的。mongodb支持两种方式的数据复制,简单的主从配置和互为主从的配置。
MongoDB分布式部署之分片配置可见
一、主从配置(Master Slave)
主从数据库需要两个数据库节点即可,一主一从(并不一定非得两台独立的服务器,可使用–dbpath参数指定数据库目录)。
$ bin/mongod –master [--dbpath /data/masterdb/]
于是,主服务器进程就会创建一个local.oplog.$main数据集(local是db),即”transaction log”,以记录从服务器需要的操作队列信息。
配置一个从数据库节点:
$ bin/mongod –slave [--source [: ]] [--dbpath /data/slavedb/]
主节点的信息会存放在从节点的 local.sources数据集中,也可以不指定–source参数,而是往local.sources中增加一条包含主节点信息的记录。
$ bin/mongo /local
> use local
> db.sources.find(); // confirms the collection is empty. then:
> db.sources.insert( { host: } );
host: 主节点的ip地址或域名全称,可跟上:port指定端口。
如果指定了only: databasename (optional) ,表示只有指定的数据库才复制,注:v1.2.1+修复了only的一个bug。
一个从节点可以有多个主节点,这种情况下,local.sources中会有多条配置信息。
一台服务器可以同时即为主也为从。如果一台从节点与主节点不同步,比如从节点的数据更新远远跟不上主节点或者从节点中断之后重启但主节点中相关的数据更新日志却不可用了。这种情况下,复制操作将会终止,需要管理者的介入,看是否默认需要重启复制操作。管理者可以使用{resync:1} 命令重启复制操作,可选命令行参数 –autoresync可使从节点在不同步情况发生10秒钟之后,自动重启复制操作。如果指定了–autoresync参数,从节点在10分钟以内自动重新同步数据的操作只会执行一次。
–oplogSize命令行参数(与–master一同使用)配置用于存储给从节点可用的更新信息占用的磁盘空间(M为单位),如果不指定这个参数,默认大小为当前可用磁盘空间的5%(64位机器最小值为1G,32位机器为50M)。
安全性方面:
$ dbshell /admin -u -p
> use local
> db.addUser(‘repl’, );
^c
$ dbshell /admin -u -p
> use local
> db.addUser(‘repl’, );
二、互为主从(Replica Pairs)
数据库自动协调某个时间点上的主从关系。开始的时候,数据库会判断哪个是从哪个是主,一旦主服务器负载过高,另一台就会自动成为主服务器。
$ ./mongod –pairwith –arbiter
remoteserver组中的其他服务器host,可加:port指定端口。
arbiterserver 仲裁(arbiter )的host,也可指定端口。仲裁是一台mongodb服务器,用于协助判断某个时间点上的数据库主从关系。如果同组服务器在同一个交换机或相同的ec2可用区域内,就没必要使用仲裁了。如果同组服务器之间不能通信,可是使用运行在第三方机器上的仲裁,使用“抢七”方式有效地敲定主服务器,也可不使用仲裁,这样所有的服务器都假定是主服务器状态,可通过命令人工检测当前哪台数据库是主数据库:
$ ./mongo
> db.$cmd.findOne({ismaster:1});
{ “ismaster” : 0.0 , “remote” : “192.168.58.1:30001″ , “ok” : 1.0 }
一致性:故障转移机制只能够保障组中的数据库上的数据的最终一致性。如果机器L是主服务器,然后挂了,那么发生在它身上的最后几秒钟的操作信息就到达不了机器R,那么机器R在机器L恢复之前是不能执行这些操作的。
安全性:同主从的操作相同。
数据库服务器替换。当一台服务器失败了,系统能自动在线恢复。但当一台机器彻底挂了,就需要替换机器,而替换机器一开始是没有数据的,怎么办?以下会解释如何替换一组服务器中的一台机器。
假设nodes(n1,n2)中的n2挂了,需要变成nodes(n1,n3)。
1、假设n2彻底挂了下线了,不能在线恢复。
2、需要告诉n1,你的搭档已经不是n2了而是n3。可使用replacepeer 命令,检测该操作的返回值以确保操作成功。
n1> ./mongo n1/admin
> db.$cmd.findOne({replacepeer:1});
{
“info” : “adjust local.sources hostname; db restart now required”
“ok” : 1.0
}
3、使用以下命令重启n1。
n1> ./mongod –pairwith n3 –arbiter
4、启动n3。
n3> ./mongod –pairwith n1 –arbiter
注意的是,n3在与n1数据完全同步之前不能接收作为主节点的任何操作。
如果从节点设置了ok标志(db.getMongo().setSlaveOk() ),就可以查询从节点了。
三、配置案例
见《MongoDB分布式部署之分片配置》的第六个模块——案例部分,有详解。
四、java案例
1、链接mongodb:
ServerAddress right = new ServerAddress(“10.13.127.212″, 18020);
ServerAddress left = new ServerAddress(“10.13.127.211″, 18020);
Mongo mongo = new Mongo(right, left);
DB db = mongo.getDB(“test”);
db.authenticate(“test”, “test”.toCharArray());
2、插入:
BasicDBObject dbObject = new BasicDBObject();
dbObject.put(“id”, i);
dbObject.put(“time”, System.currentTimeMillis());
coll.insert(dbObject);
3、更新
coll.update(new BasicDBObject(“_id”, id), getDBObjectByLabel(mongoLabel));
4、查询,查询条件的表达式文档:
BasicDBObject dbObject = new BasicDBObject();
dbObject.put(“id”, 1); //增加查询条件
BasicDBObject sortObject = new BasicDBObject(LabelConstant.ORDER_BY,LabelConstant.ORDER_DESC);
DBCursor dbCursor = coll.find(dbObject); //不分页不排序
//cursor = coll.find(doc).skip((pageNo – 1) * pageSize).limit(pageSize).sort(sortObject); //分页排序
DBObject result = dbCursor.next(); //取数据
Mongodb集群——分片和集群2高级实例
前面我们介绍了简单的集群配置实例。在简单实例中,虽然MongoDB auto-Sharding解决了海量存储问题,和动态扩容问题,但是离我们在真实环境下面所需要的高可靠性和高可用性还有一定的距离。
下面我们就介绍一个接近实际的解决方案:
- Shard:使用Replica Sets,来确保数据的可靠性。通过这个方案,可以在每个节点有数据的备份、实现自动控制容错转移和自动恢复
- Config:使用3个配置服务器,确保元数据完整性
- Route:配合LVS,实现负载均衡,提高接入性能。
1、配置集群目录
数据存储目录:
$ mkdir -p /home/scotte .ye /data/10001
$ mkdir -p /home/scotte .ye /data/10002
$ mkdir -p /home/scotte .ye /data/10003
$ mkdir -p /home/scotte .ye /data/10011
$ mkdir -p /home/scotte .ye /data/10012
$ mkdir -p /home/scotte .ye /data/10013
$ mkdir -p /home/scotte .ye /data/config1
$ mkdir -p /home/scotte .ye /data/config2
$ mkdir -p /home/scotte .ye /data/config3
日志目录:
$ mkdir -p /home/scotte .ye /data/logs
2、配置 Shard Replica Sets
配置第一组Sets
//10001
$ . /mongod --shardsvr --fork -logpath= /home/data/logs/null -dbpath= /home/data/10001/ -port=10001 --nohttpinterface --replSet set1
//10002
$ . /mongod --shardsvr --fork -logpath= /home/data/logs/null -dbpath= /home/data/10002/ -port=10002 --nohttpinterface --replSet set1
//10003
$ . /mongod --shardsvr --fork -logpath= /home/data/logs/null -dbpath= /home/data/10003/ -port=10003 --nohttpinterface --replSet set1
配置集群
$ ./mongo -port 10001
MongoDB shell version: 2.0.2
connecting to: 127.0.0.1:10001/test
>#配置集合1
>#构建参数
>cfg={_id:'set1',
members:[{_id:1,host:'192.168.35.106:10001'},
{_id:1,host:'192.168.35.106:10002'},
{_id:1,host:'192.168.35.106:10003'}]
};
{
"_id":"set1",
"members":[
{
"_id":1,
"host":"192.168.35.106:10001"
},
{
"_id":2,
"host":"192.168.35.106:10002"
},
{
"_id":3,
"host":"192.168.35.106:10003"
}
]
}
>#让参数生效
>rs.initiate(cfg);
{
"info":"Config now saved locally. Should come online in about aminute.",
"OK":1
}
>#查看运行状态
>rs.status();
{
"set" : "set1",
"date" : ISODate("2012-02-29T12:02:46Z"),
"myState" : 2,
"syncingTo" : "192.168.35.106:10003",
"members" : [
{
"_id" : 1,
"name" : "192.168.35.106:10001",
"health" : 1,
"state" : 2,
"stateStr" : "PRIMARY",
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"self" : true
},
{
"_id" : 2,
"name" : "192.168.35.106:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1112736,
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"lastHeartbeat" : ISODate("2012-02-29T12:02:45Z"),
"pingMs" : 0
},
{
"_id" : 3,
"name" : "192.168.35.106:10003",
"health" : 1,
"state" : 1,
"stateStr" : "SECONDARY",
"uptime" : 1112736,
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"lastHeartbeat" : ISODate("2012-02-29T12:02:46Z"),
"pingMs" : 0
}
],
"ok" : 1
}
配置第二组sets
//10011
$ ./mongod --shardsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/10011/ -port=10011 --nohttpinterface --replSet set2
//10012
$ ./mongod --shardsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/10012/ -port=10012 --nohttpinterface --replSet set2
//10013
$ ./mongod --shardsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/10013/ -port=10013 --nohttpinterface --replSet set2
配置集群
$ ./mongo -port 10011
MongoDB shell version: 2.0.2
connecting to: 127.0.0.1:10011/test
>#配置集合1
>#构建参数
>cfg={_id:'set2',
members:[{_id:1,host:'192.168.35.106:10011'},
{_id:1,host:'192.168.35.106:10012'},
{_id:1,host:'192.168.35.106:10013'}]
};
{
"_id":"set2",
"members":[
{
"_id":1,
"host":"192.168.35.106:10011"
},
{
"_id":2,
"host":"192.168.35.106:10012"
},
{
"_id":3,
"host":"192.168.35.106:10013"
}
]
}
>#让参数生效
>rs.initiate(cfg);
{
"info":"Config now saved locally. Should come online in about aminute.",
"OK":1
}
>#查看运行状态
>rs.status();
{
"set" : "set2",
"date" : ISODate("2012-02-29T12:12:46Z"),
"myState" : 2,
"syncingTo" : "192.168.35.106:10011",
"members" : [
{
"_id" : 1,
"name" : "192.168.35.106:10011",
"health" : 1,
"state" : 2,
"stateStr" : "PRIMARY",
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"self" : true
},
{
"_id" : 2,
"name" : "192.168.35.106:10012",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1112736,
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"lastHeartbeat" : ISODate("2012-02-29T12:02:45Z"),
"pingMs" : 0
},
{
"_id" : 3,
"name" : "192.168.35.106:10013",
"health" : 1,
"state" : 1,
"stateStr" : "SECONDARY",
"uptime" : 1112736,
"optime" : {
"t" : 1330435339000,
"i" : 2413
},
"optimeDate" : ISODate("2012-02-28T13:22:19Z"),
"lastHeartbeat" : ISODate("2012-02-29T12:02:46Z"),
"pingMs" : 0
}
],
"ok" : 1
}
启用config servier
$ ./mongod --configsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/config1/ -port=20000 --nohttpinterface
$ ./mongod --configsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/config2/ -port=20001 --nohttpinterface
$ ./mongod --configsvr --fork -logpath=/home/data/logs/null -dbpath=/home/data/config3/ -port=20002 --nohttpinterface
启用Route server
$ ./mongos -configdb="192.168.35.106:20000,192.168.35.106:20001,192.168.35.106:20002" --fork -logpath=/home/data/logs/null
>#查看是否正常运行
>ps aux|grep mongos|grep -v grep
root 2726 0.0 0.1 174192 3392 ? Sl Feb16 3:20 ./mongos -configdb=192.168.35.106:20000,192.168.35.106:20001,192.168.35.106:20002 --fork -logpath=/home/data/logs/null
开始配置Sharding
$ ./mongo -port 10001
MongoDB shell version: 2.0.2
connecting to: 127.0.0.1:10001/test
>#进入管理数据库
>use admin
switched to db admin
>#添加Sharding
> db.runcommand({addshard:'set1/192.168.35.106:10001,192.168.35.106:10002,192.168.35.106:10003'})
{"shardAdded":"set1","ok":1}
> db.runCommand({addshard:'set2/192.168.35.106:10011,192.168.35.106:10012,192.168.35.106:10013'})
{"shardAdded":"set2","ok":1}
>#让test数据库支持Sharding
>db.runCommand({enablesharding:'test'})
{"ok":1}
>#让数据库中的一个集合生效,且根据ID来进行分片
>db.runCommand({shardcollection:'test.user',key:{_id:1}})
{"collectionshrded":"test.user","ok":1}
注:另外可以通过下面两个命令查看sharding情况:
>db.runCommand({listshards:1}
>printShardingStatus();
MongoDB Linux下的安装和启动
MongoDB的安装:
# wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.2.tgz
# tar zxvf mongodb-linux-x86_64-2.0.2.tgz
# mv mongodb-linux-x86_64-2.0.2 /usr/local/mongodb
# cd /data
# mkdir mongodb
# cd /usr/local/mongodb/
# touch logs
安装完毕!这个安装是史上最简单的了
启动MongoDB
# ./bin/mongod --dbpath=/data/mongodb/ --logpath=/usr/local/mongodb/logs.log --logappend --port=27017 --fork --source=127.0.0.1
php扩展MONGODB安装:
# wget http://pecl.php.net/get/mongo-1.2.6.tgz
# tar zxvf mongo-1.2.6.tgz
# cd mongo-1.2.6
# /usr/local/php/bin/phpize
# ./configure --enable-mongo=share --with-php-config=/usr/local/php/bin/php-config
# make && make installl
. /configure -- enable -mongo=share --with-php-config= /usr/local/php/bin/php-config
1. 下载MongoDB,此处下载的版本是:mongodb-linux-i686-1.8.1.tgz.tar。
http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.8.1.tgz
相关阅读:
MongoDB Linux下的安装和启动 http://www.linuxidc.com/Linux/2011-05/36309.htm
MongoDB下的高级查询示例 http://www.linuxidc.com/Linux/2011-05/36312.htm
MongoDB Java API for 插入和单collection基本查询使用示例 http://www.linuxidc.com/Linux/2011-05/36313.htm
MongoDB下的查询操作(与Java API查询操作对应) http://www.linuxidc.com/Linux/2011-05/36314.htm
2. 解压文件到某目录下,然后重命名:
1. @localhost src]# tar -xzvf mongodb-linux-i686-1.8.1.tgz.tar
2. @localhost src]# mv mongodb-linux-i686-1.8.1
3. 查看安装后的文件情况:
1. @localhost
2. @localhost
3. 3.0
4. @localhost
5. @localhost
6. bsondump dbbak mongo mongod mongodump mongoexport mongofiles mongoimport mongorestore mongos mongosniff mongostat
bin下的mongod就是MongoDB的服务端进程,mongo就是其客户端,其它的命令用于MongoDB的其它用途如MongoDB文件导出等。
4. 启动MongoDB.
要先建立好MongoDB 存放数据文件和日志文件的目录,此处建立在/data下:
1. @localhost
2. @localhost
3. mongodb_data mongodb_log
在MongoDB安装目录下的bin下使用mongod启动MongoDB,
1. ./mongod –dbpath=/data/mongodb_data/ –logpath=/data/mongodb_log/mongodb.log –logappend&
等待启动成功后,可查看是否启动成功了,默认端口号是27017,当然在启动时也可以指定未使用的其它端口。
先通过查看端口号看MongoDB是否启动了。
1. @localhost data]# netstat -lanp | grep “27017″
2. 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 1573/mongod
3. 2 [ ACC ] STREAM LISTENING 5874 1573/mongod /tmp/mongodb-27017.sock
可以看到,已启动成功,现在使用mongo客户端访问一下该数据库。
1. @localhost
2. @localhost
3. 1.8.1
4. connecting to: test
5. >
到这一步说明已经安装成功了。
5. 额外工作。
注意,上述我们启动MongoDB都是手动使用mongod来启动,这样关闭计算机后,下次再进来它又没启动了,所以还得手动启动,因此,为避免这种繁琐的工作,可以把mongod放到服务自启动项中,这样计算机一开启mongod服务也就启动了。
编辑/etc/rc.local,加入下述代码然后再保存即可。
1. #add mongonDB service
2. rm -rf /data/mongodb_data/* && /usr/local/mongodb/bin/mongod –dbpath=/data/mongodb_data/ –logpath=/data/mongodb_log/mongodb.log –logappend&
我们重启计算机再看MongoDB是否启动,重启后可以直接使用 mongo命令登录,最终发现是可以成功的。
另外,我们使用mongo命令登录 MongoDB还要转到mongo命令所在目录再执行./mongo,这样是不是有些麻烦?因此,我们可以简化这点,将该命令文件copy到/usr/bin下,这样就可以在任何目录下使用mongo命令了。
1. @localhost
2. bsondump dbbak mongo mongod mongodump mongoexport mongofiles mongoimport mongorestore mongos mongosniff mongostat
3. @localhost
转到任一目录试下mongo命令:
1. @localhost
2. @localhost
3. 1.8.1
4. connecting to: test
5. >
可以看到登录成功了,说明我们可以像使用ls命令一样使用mongo命令了。
MySQL与MongoDB的操作对比
MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库。它们各有各的优点,关键是看用在什么地方。
以我们公司项目为例,在早期的项目中,都在使用关系型数据库,用过SQLServer,Oracle,DB2,后来全部转向Mysql,原因很简 单:Mysql在性能不错的情况下,有着开源优势。Mysql的事务性与高性能是我们主要考虑的。后来,由于项目要用到用户系统,即会有大量的用户数据进 行交互--海量存储,Mysql的读写速度会有一点瓶颈,于是我们就想到了最近发展很强势的Nosql。在Nosql早期的memcache的发展下,又 出现了很多非关系型数据库,比如redis,mongodb。经过一段时间的测试,redis与mongodb的读写速度确实比Mysql有着很明显的优 势。mongodb的写入速度大约2.5W/次每秒。
mongodb以BSON结构(二进制)进行存储,对海量数据存储有着很明显的优势。下面是Mongodb与Mysql的操作命令的对比。
作用 | MySQL | MongoDB |
| | |
服务器守护进程 | mysqld | mongod |
客户端工具 | mysql | mongo |
逻辑备份工具 | mysqldump | mongodump |
逻辑还原工具 | mysql | mongorestore |
数据导出工具 | mysqldump | mongoexport |
数据导入工具 | source | mongoimport |
| | |
新建用户并授权 | grant all on *.* to username@’localhost’ identified by ‘passwd’; | db.addUser(“user”,”psw”) db.auth(“user”,”psw”) |
显示库列表 | show databases; | show dbs |
进去库 | use dbname; | use dbname |
显示表列表 | show tables; | show collections |
查询主从状态 | show slave status; | rs.status |
创建库 | create database name; | 无需单独创建,直接use进去 |
创建表 | create table tname(id int); | 无需单独创建,直接插入数据 |
删除表 | drop table tname; | db.tname.drop() |
删除库 | drop database dbname; | 首先进去该库,db.dropDatabase() |
| | |
插入记录 | insert into tname(id) value(2); | db.tname.insert({id:2}) |
删除记录 | delete from tname where id=2; | db.tname.remove({id:2}) |
修改/更新记录 | update tname set id=3 where id=2; | db.tname.update({id:2}, {$set:{id:3}},false,true) |
| | |
查询所有记录 | select * from tname; | db.tname.find() |
查询所有列 | select id from tname; | db.tname.find({},{id:1}) |
条件查询 | select * from tname where id=2; | db.tname.find({id:2}) |
条件查询 | select * from tname where id < 2; | db.tname.find({id:{$lt:2}}) |
条件查询 | select * from tname where id >=2; | db.tname.find({id:{$gte:2}}) |
条件查询 | select * from tname where id=2 and name=’steve’; | db.tname.find({id:2, name:’steve’}) |
条件查询 | select * from tname where id=2 or name=’steve’; | db.tname.find($or:[{id:2}, {name:'steve'}]) |
条件查询 | select * from tname limit 1; | db.tname.findOne() |
| | |
模糊查询 | select * from tname where name like “%ste%”; | db.tname.find({name:/ste/}) |
模糊查询 | select * from tname where name like “ste%”; | db.tname.find({name:/^ste/}) |
| | |
获取表记录数 | select count(id) from tname; | db.tname.count() |
获取有条件 的记录数 | select count(id) from tname where id=2; | db.tname.find({id:2}).count() |
查询时去掉 重复值 | select distinct(last_name) from tname; | db.tname.distinct(‘last_name’) |
| | |
正排序查询 | select *from tname order by id; | db.tname.find().sort({id:1}) |
逆排序查询 | select *from tname order by id desc; | db.tname.find().sort({id:-1}) |
| | |
取存储路径 | explain select * from tname where id=3; | db.tname.find({id=3}).explain() |
特别要注意的是:mongodb插入多个字段语法
> db.user.insert({id:1,name:’steve’,sex:’male’}) 正确
> db.user.insert({id:2},{name:’bear’},{sex:’female’}) 错误
用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 $options)
array $a 要插入的数组
array $options 选项
safe 是否返回操作结果信息
fsync 是否直接插入到物理硬盘
例程:
$coll = $mo->db->foo;
$a = array(’a’=>’b’);
$options = array(’safe’=>true);
$rs =$coll->insert($a,$options);
$rs为一个array型的数组,包含操作信息
删除数据库中的记录(MongoCollection对象):
http://us.php.net/manual/en/mongocollection.remove.php
MongoCollection::remove(array $criteria,array $options)
array $criteria 条件
array $options 选项
safe 是否返回操作结果
fsync 是否是直接影响到物理硬盘
justOne 是否只影响一条记录
例程:
$coll = $mo->db->coll;
$c = array(’a’=>1,’s’=>array(’$lt’=>100));
$options = array(’safe’=>true);
$rs = $coll->remove($c,$options);
$rs为一个array型的数组,包含操作信息
更新数据库中的记录(MongoCollection对象):
http://us.php.net/manual/en/mongocollection.update.php
MongoCollection::update(array $criceria,array $newobj,array $options)
array $criteria 条件
array $newobj 要更新的内容
array $options 选项
safe 是否返回操作结果
fsync 是否是直接影响到物理硬盘
upsert 是否没有匹配数据就添加一条新的
multiple 是否影响所有符合条件的记录,默认只影响一条
例程:
$coll = $mo->db->coll;
$c = array(’a’=>1,’s’=>array(’$lt’=>100));
$newobj = array(’e’=>’f’,’x’=>’y’);
$options = array(’safe’=>true,’multiple’=>true);
$rs = $coll->update($c,$newobj,$options);
$rs为一个array型的数组,包含操作信息
查询collection获得单条记录(MongoCollection类):
http://us.php.net/manual/en/mongocollection.findone.php
array MongoCollection::findOne(array $query,array $fields)
array $query 条件
array $fields 要获得的字段
例程:
$coll = $mo->db->coll;
$query = array(’s’=>array(’$lt’=>100));
$fields = array(’a’=>true,’b’=>true);
$rs = $coll->findOne($query,$fields);
如果有结果就返回一个array,如果没有结果就返回NULL
查询collection获得多条记录(MongoCollection类):
http://us.php.net/manual/en/mongocollection.find.php
MongoCursor MongoCollection::find(array $query,array $fields)
array $query 条件
array $fields 要获得的字段
例程:
$coll = $mo->db->coll;
$query = array(’s’=>array(’$lt’=>100));
$fields = array(’a’=>true,’b’=>true);
$cursor = $coll->find($query,$fields);
返回一个游标记录对象MongoCursor。
针对游标对象MongoCursor的操作(MongoCursor类):
http://us.php.net/manual/en/class.mongocursor.php
循环或的结果记录:
$cursor = $coll->find($query,$fields);
while($cursor->hasNext()){
$r = $cursor->getNext();
var_dump($r);
}
或者
$cursor = $coll->find($query,$fields);
foreache($cursor as $k=>$v){
var_dump($v);
}
或者
$cursor = $coll->find($query,$fields);
$array= iterator_to_array($cursor);
一个血的教训:
http://us.php.net/manual/en/mongocursor.snapshot.php
详见 不断变化的MongDB结果集
在我们做了find()操作,获得$cursor游标之后,这个游标还是动态的,也就是在我获得游标到我循环操作完成对应记录的过程中,默认情况下,这对符合条件的记录如果增加,结果集也会自动增加。换句话说,在我find()之后,到我的游标循环完成这段时间,如果再有符合条件的记录被插入到collection,那么这些记录也会被$cursor获得。
如果你想在获得$cursor之后的结果集不变化,需要这样做:
$cursor = $coll->find($query,$fields);
$cursor->snapshot();
foreache($cursor as $k=>$v){
var_dump($v);
}
MongoDB常用的操作命令
- 超级用户相关:
- use admin
- #增加或修改用户密码
- db.addUser(ixigua,’pwd’)
- #查看用户列表
- db.system.users.find()
- #用户认证
- db.auth(ixigua,’pwd’)
- #删除用户
- db.removeUser(‘mongodb’)
- #查看所有用户
- show users
- #查看所有数据库
- show dbs
- #查看所有的collection
- show collections
- #查看各collection的状态
- db.printCollectionStats()
- #查看主从复制状态
- db.printReplicationInfo()
- #修复数据库
- db.repairDatabase()
- #设置记录profiling,0=off 1=slow 2=all
- db.setProfilingLevel(1)
- #查看profiling
- show profile
- #拷贝数据库
- db.copyDatabase(‘mail_addr’,'mail_addr_tmp’)
- #删除collection
- db.mail_addr.drop()
- #删除当前的数据库
- db.dropDatabase()
- 客户端连接
- /usr/local/mongodb/bin/mongo 8.8.88/ixigualib -u ixigua -p ‘pwd’
- 增删改
- #存储嵌套的对象
- db.foo.save({‘name’:'ysz’,'address’:{‘city’:'beijing’,'post’:100096},’phone’:[138,139]})
- #存储数组对象
- db.user_addr.save({‘Uid’:'yushunzhi@sohu.com’,'Al’:['test-1@sohu.com','test-2@sohu.com']})
- #根据query条件修改,如果不存在则插入,允许修改多条记录
- db.foo.update({‘yy’:5},{‘$set’:{‘xx’:2}},upsert=true,multi=true)
- #删除yy=5的记录
- db.foo.remove({‘yy’:5})
- #删除所有的记录
- db.foo.remove()
- 索引
- #增加索引:1(ascending),-1(descending)
- db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
- #索引子对象
- db.user_addr.ensureIndex({‘Al.Em’: 1})
- #查看索引信息
- db.deliver_status.getIndexes()
- db.deliver_status.getIndexKeys()
- #根据索引名删除索引
- db.user_addr.dropIndex(‘Al.Em_1′)
- 查询
- #查找所有
- db.foo.find()
- #查找一条记录
- db.foo.findOne()
- #根据条件检索10条记录
- db.foo.find({‘msg’:'Hello 1′}).limit(10)
- #sort排序
- db.deliver_status.find({‘From’:'ixigua@sina.com’}).sort({‘Dt’,-1})
- db.deliver_status.find().sort({‘Ct’:-1}).limit(1)
- #count操作
- db.user_addr.count()
- #distinct操作
- db.foo.distinct(‘msg’)
- #>操作
- db.foo.find({“timestamp”: {“$gte” : 2}})
- #子对象的查找
- db.foo.find({‘address.city’:'beijing’})
- 管理
- #查看collection数据的大小
- db.deliver_status.dataSize()
- #查看colleciont状态
- db.deliver_status.stats()
- #查询所有索引的大小
- db.deliver_status.totalIndexSize()