有用的命令
db.help db.collectionname.help
时区问题
> db.test.insert({"date":new Date("2012-2-2"),"num":1}) > db.test.insert({"date":new Date("2012-02-02"),"num":2}) > db.test.insert({"date":new Date("2012-02-02 00:00:00"),"num":3}) > db.test.find() { "_id" : ObjectId("538ebd629ceb8ee60dcd6a0e"), "date" : ISODate("2012-02-01T16:00:00Z"), "num" : 1 } { "_id" : ObjectId("538ebd6e9ceb8ee60dcd6a0f"), "date" : ISODate("2012-02-02T00:00:00Z"), "num" : 2 } { "_id" : ObjectId("538ebd7e9ceb8ee60dcd6a10"), "date" : ISODate("2012-02-01T16:00:00Z"), "num" : 3 } > db.test.find() { "_id" : ObjectId("538ebd629ceb8ee60dcd6a0e"), "date" : ISODate("2012-02-01T16:00:00Z"), "num" : 1 } { "_id" : ObjectId("538ebd6e9ceb8ee60dcd6a0f"), "date" : ISODate("2012-02-02T00:00:00Z"), "num" : 2 } { "_id" : ObjectId("538ebd7e9ceb8ee60dcd6a10"), "date" : ISODate("2012-02-01T16:00:00Z"), "num" : 3 } >
开启子节点的读
rs.slaveOk();
开启 Profiling 功能
db.setProfilingLevel(2);
上面profile的级别可以取0,1,2 三个值,他们表示的意义如下:
0 – 不开启
1 – 记录慢命令 (默认为>100ms)
2 – 记录所有命令
Profile 记录在级别 1 时会记录慢命令,那么这个慢的定义是什么?上面我们说到其默认为100ms,当然有默认就有设置,其设置方法和级别一样有两种,一种是通过添加–slowms 启动参数配置。第二种是调用db.setProfilingLevel时加上第二个参数:
db.setProfilingLevel( 1 , 10 );
查询 Profiling 记录
db.system.profile.find( { millis : { $gt : 5 } } )
查看最新的 Profile 记录:
db.system.profile.find().sort({$natural:-1}).limit(1)
{ "ts" : ISODate("2012-05-20T16:50:36.321Z"), "info" : "query test.system.profile reslen:1219
字段说明
1ms的 Profile 记录。
db.ttl.ensureIndex({
"Date"
: 1}, {expireAfterSeconds: 300})
cfg = { _id: "set1", members: [
... { _id:0, host:"10.96.16.118:27017" },
... { _id:1, host:"10.96.16.119:27017" },
... { _id:2, host:"10.96.22.40:27022" , "arbiterOnly": true}
... ]}
rs.initiate(cfg)
收缩日志
在admin数据库下执行
db.runCommand({logRotate:1}) mongodb会重新写个日志
上篇讲过每个集群结点都有一个priority属性,默认为1。要改变一个实例的角色,我们只需要给新的实例设置一个高于当前Primary的priority就可以实现了。
注意因为只有Primary结点是可写的,所以重新配置群集的操作只能在Primary结点上进行。
rs0:PRIMARY> conf.members[1].priority = 2 2 rs0:PRIMARY> rs.reconfig(conf) Fri Jan 24 15:25:36.069 DBClientCursor::init call() failed Fri Jan 24 15:25:36.070 trying reconnect to localhost:27011 Fri Jan 24 15:25:36.070 reconnect localhost:27011 ok reconnected to server after rs command (which is normal) rs0:SECONDARY>
追加内容(numa服务器下mongodb的部署)
numactl --interleave=all ./mongod -f ./mongodb.conf
0:追加内容(MapReduce)
MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。这样做的好处是可以在任务被分解后,可以通过大量机器进行并行计算,减少整个操作的时间。
举例1
数据
for (var i = 0; i < 10; i++) { ... var u = { name : "user" + i, age : i, sex : i % 2 }; ... db.users.insert(u); ... }
A:男女同学分别的人数(select Sex,count(*) from users group by Sex)
m = function() { emit(this.sex, 1) } r = function(key, values) { ... ... var x = 0; ... ... values.forEach(function(v) { x += v ;}); ... ... return x; ... ... }
B: 男女同学的平均年龄(select Sex,avg(age) from users group by Sex)
m = function() { emit(this.sex, this.age) } r = function(key, values) { ... ... var x = 0,num=0; ... ... values.forEach(function(v) { x += v ;num++}); ... ... return x/num; ... ... }
另一个例子,计算一个标签系统中每个标签出现的次数
> db.things.insert( { _id : 1, tags : ['dog', 'cat'] } ); > db.things.insert( { _id : 2, tags : ['cat'] } ); > db.things.insert( { _id : 3, tags : ['mouse', 'cat', 'dog'] } ); > db.things.insert( { _id : 4, tags : [] } ); > // map function > m = function(){ ... this.tags.forEach( ... function(z){ ... emit( z , { count : 1 } ); ... } ... ); ...}; > // reduce function > r = function( key , values ){ ... var total = 0; ... for ( var i=0; i<values.length; i++ ) ... total += values[i].count; ... return { count : total }; ...}; > res = db.things.mapReduce(m, r, { out : "myoutput" } ); > res { "result" : "myoutput", "timeMillis" : 12, "counts" : { "input" : 4, "emit" : 6, "output" : 3 }, "ok" : 1, } > db.myoutput.find() {"_id" : "cat" , "value" : {"count" : 3}} {"_id" : "dog" , "value" : {"count" : 2}} {"_id" : "mouse" , "value" : {"count" : 1}} > db.myoutput.drop()
从上面的三个列子我们可以看出
1:map函数只要用于从样本空间中过滤出key-values集合,其中key就是emit的第一个参数,values就是第二个参数
2:reduce函数主要是要将key-values转换成key-value的形式,也就是把这一个集合变成一个单一的值
1:各文件作用
mongo.exe 客户端程序 mongod.exe 服务端程序 mongodump.exe 备份程序 mongoexport.exe 数据导出程序 mongofiles.exe GridFS工具,内建的分布式文件系统 mongoimport.exe 数据导入程序 mongorestore.exe 数据恢复程序 mongos.exe 数据分片程序,支持数据的横向扩展 mongostat.exe 监视程序
2:部署
MongoDB可以以DOS作为容器运行也可以以服务形式运行。
以DOS为容器运行
mongod --dbpath E:\mongodb\bin\db -- port 27020 --logpath E:\mongodb\bin\log.txt
--directoryperdb 让系统为每个 DB 创建一个独立子目录
与 Logging 有关的参数除了 --logpath,还有 --logappend 和 --verbose。
默认情况下,Logging 是覆盖模式(overwrite),通过 --logappend 可以添加模式记录日志。
参数 --verbose 设置记录等级,相当于 -v,更多的级别包括 -vv 直到 -vvvvv。与之相对的是 --quiet,生成最少的日志信息。
还可以用 --cpu 记录 CPU 的相关信息。
admin.serverStatus() 命令可以获取 MongoDB 的运行统计信息。(uptime: 服务器运行时间(秒)。localTime: 服务器本地时间。mem: 服务器内存信息。connections: 当前连接数。opcounters: 操作统计。)
db.stats 查看数据库状态信息。
以WindowsServer为容器运行
mongod --dbpath E:\mongodb\bin\db --logpath E:\mongodb\bin\log.txt --install
以服务方式运行不能指定端口。
验证方法
mongo --port 27017 show dbs
3:复制数据库
同数据库系统复制
E:\mongodb\bin>mongo MongoDB shell version: 1.8.2 connecting to: test > use person switched to db person > for (var i = 0; i < 10; i++) db.person.save({id : + i}) > show dbs admin (empty) local (empty) person 0.03125GB > db.copyDatabase("person","person1") { "ok" : 1 } > show dbs admin (empty) local (empty) person 0.03125GB person1 0.03125GB
异数据库系统复制
E:\mongodb\bin>mongo --port 27020 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27020/test > show dbs admin (empty) local (empty) > db.copyDatabase("person", "person2", "10.53.139.138:27017") { "ok" : 1 } > show dbs admin (empty) local (empty) person2 0.03125GB
4:锁定数据库
> db.person.find() { "_id" : ObjectId("4e27baae7ff2440ba274d767"), "id" : 0 } { "_id" : ObjectId("4e27baae7ff2440ba274d768"), "id" : 1 } { "_id" : ObjectId("4e27baae7ff2440ba274d769"), "id" : 2 } { "_id" : ObjectId("4e27baae7ff2440ba274d76a"), "id" : 3 } { "_id" : ObjectId("4e27baae7ff2440ba274d76b"), "id" : 4 } { "_id" : ObjectId("4e27baae7ff2440ba274d76c"), "id" : 5 } { "_id" : ObjectId("4e27baae7ff2440ba274d76d"), "id" : 6 } { "_id" : ObjectId("4e27baae7ff2440ba274d76e"), "id" : 7 } { "_id" : ObjectId("4e27baae7ff2440ba274d76f"), "id" : 8 } { "_id" : ObjectId("4e27baae7ff2440ba274d770"), "id" : 9 } { "_id" : ObjectId("4e27bf5c9033de6afd328581"), "id" : 10 } > admin=db.getSisterDB("admin") admin > admin.runCommand({fsync : 1, lock : 1}) //锁定 { "info" : "now locked against writes, use db.$cmd.sys.unlock.findOne() to unlock", "ok" : 1 } > db.person.find()//锁定期间可读 { "_id" : ObjectId("4e27baae7ff2440ba274d767"), "id" : 0 } { "_id" : ObjectId("4e27baae7ff2440ba274d768"), "id" : 1 } { "_id" : ObjectId("4e27baae7ff2440ba274d769"), "id" : 2 } { "_id" : ObjectId("4e27baae7ff2440ba274d76a"), "id" : 3 } { "_id" : ObjectId("4e27baae7ff2440ba274d76b"), "id" : 4 } { "_id" : ObjectId("4e27baae7ff2440ba274d76c"), "id" : 5 } { "_id" : ObjectId("4e27baae7ff2440ba274d76d"), "id" : 6 } { "_id" : ObjectId("4e27baae7ff2440ba274d76e"), "id" : 7 } { "_id" : ObjectId("4e27baae7ff2440ba274d76f"), "id" : 8 } { "_id" : ObjectId("4e27baae7ff2440ba274d770"), "id" : 9 } { "_id" : ObjectId("4e27bf5c9033de6afd328581"), "id" : 10 } > db.person.save({id : 11 })////锁定期间写被阻塞 ----------------- 另开CMD E:\mongodb\bin>mongo MongoDB shell version: 1.8.2 connecting to: test > use admin switched to db admin > db.$cmd.sys.unlock.findOne() { "ok" : 1, "info" : "unlock requested" } ------------------ > db.person.find() { "_id" : ObjectId("4e27baae7ff2440ba274d767"), "id" : 0 } { "_id" : ObjectId("4e27baae7ff2440ba274d768"), "id" : 1 } { "_id" : ObjectId("4e27baae7ff2440ba274d769"), "id" : 2 } { "_id" : ObjectId("4e27baae7ff2440ba274d76a"), "id" : 3 } { "_id" : ObjectId("4e27baae7ff2440ba274d76b"), "id" : 4 } { "_id" : ObjectId("4e27baae7ff2440ba274d76c"), "id" : 5 } { "_id" : ObjectId("4e27baae7ff2440ba274d76d"), "id" : 6 } { "_id" : ObjectId("4e27baae7ff2440ba274d76e"), "id" : 7 } { "_id" : ObjectId("4e27baae7ff2440ba274d76f"), "id" : 8 } { "_id" : ObjectId("4e27baae7ff2440ba274d770"), "id" : 9 } { "_id" : ObjectId("4e27bf5c9033de6afd328581"), "id" : 10 } { "_id" : ObjectId("4e27bfe99033de6afd328582"), "id" : 11 }
需要注意:两次锁定时第二次会等待第一次锁释放,锁定的时候当第一次有写操作时在没有解锁前所有的操作都不能进行。
5:备份与恢复
(完成person从27020备份然后还原到27017)
备份
E:\mongodb\bin>mongodump -h 10.53.139.138:27020 -d person2 -o E:\mongodb\bin\back connected to: 10.53.139.138:27020 DATABASE: person2 to E:/mongodb/bin/back/person2 person2.person to E:/mongodb/bin/back/person2/person.bson 10 objects person2.system.indexes to E:/mongodb/bin/back/person2/system.indexes.bson 1 objects
恢复
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) blog (empty) local (empty) person 0.03125GB person1 0.03125GB persons (empty) > exit bye E:\mongodb\bin>mongorestore -h 10.53.139.138:27017 --directoryperdb E:\mongodb\b in\back\person2 connected to: 10.53.139.138:27017 Thu Jul 21 14:36:10 E:/mongodb/bin/back/person2/person.bson Thu Jul 21 14:36:10 going into namespace [person2.person] Thu Jul 21 14:36:10 10 objects found Thu Jul 21 14:36:10 E:/mongodb/bin/back/person2/system.indexes.bson Thu Jul 21 14:36:10 going into namespace [person2.system.indexes] Thu Jul 21 14:36:10 { name: "_id_", ns: "person2.person", key: { _id: 1 }, v: 0 } Thu Jul 21 14:36:10 1 objects found E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) blog (empty) local (empty) person 0.03125GB person1 0.03125GB person2 0.03125GB persons (empty)
公共参数:
--port arg 指定端口
-h arg 指定主机
-d arg 指定database
-c arg 指定collection
--dbpath arg 指定mongod的数据库文件所在路径
备份:
bsondump
命令用法:bsondump [options] <bson fileName>
特别参数:
--type arg 输出文件的格式,arg= json,debug在xp下不能用,没测试
mongodump
命令用法:mongodump [options]
特别参数:
-o arg 输出的"目录",不指定时,默认在执行命令的路径下创建dump目录导出
-q arg json query,此处可通过json查询,有选择性的导出数据
说明:
1.与mongorestore构成一对工具集,即由Mongodump导出的数据可由mongrestore恢复
2.mongodump可用于“热备份”
3.导出的数据是bson格式
性能:数据库中1g的数据导出后变成285M,大概8秒
备注 1. mogodump / mongorestore 这2命令将mongodb的数据dump为BSON格式,需要的时候可以恢复。 这种方式作为小的数据库还适用。但如果是sharding或者几百G数据以上的话 就几乎不可用了。因为BSON及其占用空间。 特别注意的是备份前执行db.runCommand({fsync : 1})将内存中的数据刷到文件中。 2. Slave Replication 这是最适合和可靠的,适合生产环境。MongoDb支持master+多个slave。因此可以很方便的起一个slave来进行备份。 但是需要注意的是如果数据量很大的话,如果是新建的slave,速度又没有保证的话,一定要调高 oplogSize 的大小,对于一个300G的数据库, 可以调到60G以上。这样避免同步到中间出现oplogSize不足等异常。 3. 关于增量热备份 对于某些热衷单独文件备份的同志,也可以考虑使用“增量热”备份的方式作为最后的屏障。 做法就是,最开始将某个slave暂时shutdown,然后将数据库文件复制到另一个目录作为增量备份的起点。 每次备份的时候,在这个目录上起一个slave, 使用–fastsync参数,同步完毕即可tar这个目录就可以了。 这种方式的一个缺点就是如果备份周期的过长的话,空间浪费会非常大,尤其是频繁删除的情况下, 目前1.6以前的版本对于删除的空间回收机制有bug。这个问题应该在1.6版本发布时候解决。 要想回收这些空间需要repairDatabase,速度比较慢,不如直接从头clone一个新的db了。(其实Repair的过程也就是先clone然后copy回来)。 综上所述, 最靠谱和安全的备份方式就是用mongodb自身的同步复制机制. 最经典也最小的生产环境是: 1 master + 2 slaves
6:导入与导出
导出(文件要预先建立)
E:\mongodb\bin>mongoexport -h 10.53.139.138 -d person -c person -o E:\mongodb\bin\aa.bson connected to: 10.53.139.138 exported 14 records
导入
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) blog (empty) local (empty) person 0.03125GB person1 0.03125GB person2 0.03125GB persons (empty) > exit bye E:\mongodb\bin>mongoimport -h 10.53.139.138 --port 27017 -d person3 -c person -- file E:\mongodb\bin\aa.bson connected to: 10.53.139.138:27017 imported 14 objects E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) blog (empty) local (empty) person 0.03125GB person1 0.03125GB person2 0.03125GB person3 0.03125GB persons (empty)
7:操作
插入
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) local (empty) test (empty) > use company switched to db company > u={name:"dabing",id:1} { "name" : "dabing", "id" : 1 } > db.person.insert(u) > db.person.find() { "_id" : ObjectId("4e27d1edb449d8dc5d763a57"), "name" : "dabing", "id" : 1 } > u.id+=1 2 > db.person.save(u) > db.person.find() { "_id" : ObjectId("4e27d1edb449d8dc5d763a57"), "name" : "dabing", "id" : 1 } { "_id" : ObjectId("4e27d228b449d8dc5d763a58"), "name" : "dabing", "id" : 2 } > u=db.person.findOne({id:1}) { "_id" : ObjectId("4e27d1edb449d8dc5d763a57"), "name" : "dabing", "id" : 1 } > u.id+=2 3 > db.person.save(u) > db.person.find() { "_id" : ObjectId("4e27d1edb449d8dc5d763a57"), "name" : "dabing", "id" : 3 } { "_id" : ObjectId("4e27d228b449d8dc5d763a58"), "name" : "dabing", "id" : 2 }
save() 可插入新文档,也可以更新(update)一个已有的文档
查询函数式有 find() 和 findOne(),前者返回一个迭代器 cursor,后者返回单个文档
查询
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) local (empty) test (empty) > show dbs admin (empty) local (empty) test (empty) > use company switched to db company > for (var i = 0; i < 10; i++) db.users.insert({name:"user" + i, age:20 + i, sex:i % 2}) > db.users.find({name:"user1"}) //select * from users where name = 'user1' { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } > db.users.find({name:"user1",age:1}) > db.users.find({name:"user1",age:21}) //select * from users where name = 'user1' and age = 21 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } > db.users.find({name:"user1",age:21},{name:1}) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1" } > db.users.find({name:"user1",age:21},{name:1,age:1}) //select name,age from users where name = 'user1' and age = 21 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21 } > db.users.find().sort({age:1}) //select * from users order by age asc { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5d"), "name" : "user4", "age" : 24, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a62"), "name" : "user9", "age" : 29, "sex" : 1 } > db.users.find().sort({age:-1})//select * from users order by age desc { "_id" : ObjectId("4e27d3e2b449d8dc5d763a62"), "name" : "user9", "age" : 29, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5d"), "name" : "user4", "age" : 24, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } > db.users.find().sort({sex:-1,age:-1}) //select * from users order by sex asce, age desc { "_id" : ObjectId("4e27d3e2b449d8dc5d763a62"), "name" : "user9", "age" : 29, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5d"), "name" : "user4", "age" : 24, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } > db.users.find().sort({sex:-1,age:-1}).skip(2).limit(3)//select * from users skip 2 limit 3 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } > db.users.find({sex:1, age:{$gt:23, $lt:28}})//select * from users where sex = 1 and age > 23 and age < 28 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } 比较操作包括:$gt (>)、$lt (<)、$gte (>=)、$lte(<=)、$ne (!=) > db.users.find({age:{$in:[23,26,32]}}) //select * from users where age in (23, 26, 32) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } 对应的操作符有 $nin (not in) > db.users.find({age:{$gt:20}}).count()//select count(*) from users where age > 20 9 > db.users.find({$or:[{age:25}, {age:28}]})//select * from users where age = 25 or age = 28 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } > db.users.find({$or:[{age:{$lte:23}}, {age:{$gte:33}}]})//select * from users where age <= 23 or age >= 33 { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 21, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 }
更新
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > show dbs admin (empty) company 0.03125GB local (empty) test (empty) > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 100, "sex" : 0 } //db.collection.update(criteria, objNew, upsert, mult) //criteria: 需要被更新的条件表达式 //objNew: 更新表达式 //upsert: 如目标记录不存在,是否插入新文档。 //multi: 是否更新多个文档。 > db.users.update({name:"user1"}, {$set:{age:101, sex:0}})//update users set age = 101, sex = 0 where name = 'user1' > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 101, "sex" : 0 } > db.users.update({name:"user1"}, {$inc:{age:10}}, false, true)//update users set age = age + 10 where name = 'user1' > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 111, "sex" : 0 } > db.users.update({name:"user1"}, {$inc:{age:10}, $set:{sex:1}})//update users set age = age + 10, sex = 1 where name = 'user1' > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 121, "sex" : 1 }
删除
> db.users.find() { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 121, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5c"), "name" : "user3", "age" : 23, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5d"), "name" : "user4", "age" : 24, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a62"), "name" : "user9", "age" : 29, "sex" : 1 } > db.users.remove({name:"user3"}) > db.users.find() { "_id" : ObjectId("4e27d3e2b449d8dc5d763a59"), "name" : "user0", "age" : 20, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5a"), "name" : "user1", "age" : 121, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5b"), "name" : "user2", "age" : 22, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5d"), "name" : "user4", "age" : 24, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5e"), "name" : "user5", "age" : 25, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a5f"), "name" : "user6", "age" : 26, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a60"), "name" : "user7", "age" : 27, "sex" : 1 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a61"), "name" : "user8", "age" : 28, "sex" : 0 } { "_id" : ObjectId("4e27d3e2b449d8dc5d763a62"), "name" : "user9", "age" : 29, "sex" : 1 } > db.users.remove() > db.users.find()
MapReduce
E:\mongodb\bin>mongo --port 27017 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:27017/test > use blog switched to db blog >for (var i = 0; i < 1000; i++) { ... var u = { name : "user" + i, age : i % 40 + 1, sex : i % 2 }; ... db.users.insert(u); ... } > db.users.ensureIndex({name:1}) > db.users.ensureIndex({age:1}) //相当于select count(*) value,age from users group by age > m = function() { emit(this.age, 1) } function () { emit(this.age, 1); } > r = function(key, values) { ... ... var x = 0; ... ... values.forEach(function(v) { x += v });//这里可以执行批量更新操作eg ... ... return x; ... ... } ------------------//批量更新例子 r = function(key, values) { ... update = function(v) { ... db.users.update({_id:key}, {$inc:{age:1}}, false, false); ... } ... values.forEach(update); ... return key; ... } mapreduce: 要操作的目标集合。 map: 映射函数 (生成键值对序列,作为 reduce 函数参数)。 reduce: 统计函数。 query: 目标记录过滤。 sort: 目标记录排序。 limit: 限制目标记录数量。 out: 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。 keeptemp: 是否保留临时集合。 finalize: 最终处理函数 (对 reduce 返回结果进行最终整理后存入结果集合)。 scope: 向 map、reduce、finalize 导入外部变量。 verbose: 显示详细的时间统计信息。 -------------------- function (key, values) { var x = 0; values.forEach(function (v) {x += v;}); return x; } > res = db.users.mapReduce(m, r,{out:"res"}); { "result" : "res", "timeMillis" : 62, "counts" : { "input" : 1000, "emit" : 1000, "output" : 40 }, "ok" : 1, } > db.res.find() { "_id" : 1, "value" : 25 } { "_id" : 2, "value" : 25 } { "_id" : 3, "value" : 25 } { "_id" : 4, "value" : 25 } { "_id" : 5, "value" : 25 } { "_id" : 6, "value" : 25 } { "_id" : 7, "value" : 25 } { "_id" : 8, "value" : 25 } { "_id" : 9, "value" : 25 } { "_id" : 10, "value" : 25 } { "_id" : 11, "value" : 25 } { "_id" : 12, "value" : 25 } { "_id" : 13, "value" : 25 } { "_id" : 14, "value" : 25 } { "_id" : 15, "value" : 25 } { "_id" : 16, "value" : 25 } { "_id" : 17, "value" : 25 } { "_id" : 18, "value" : 25 } { "_id" : 19, "value" : 25 } { "_id" : 20, "value" : 25 } has more //可以进一步处理 > f = function(key, value) { return {age:key, count:value}; } function (key, value) { return {age:key, count:value}; } //res = db.users.mapReduce(m, r,{out:"res",finalize:f,query:{age:{$lt:10}}, sort:{name:1}, limit:5}}); > res = db.users.mapReduce(m, r,{out:"res",finalize:f}); { "result" : "res", "timeMillis" : 31, "counts" : { "input" : 1000, "emit" : 1000, "output" : 40 }, "ok" : 1, } > db.res.find() { "_id" : 1, "value" : { "age" : 1, "count" : 25 } } { "_id" : 2, "value" : { "age" : 2, "count" : 25 } } { "_id" : 3, "value" : { "age" : 3, "count" : 25 } } { "_id" : 4, "value" : { "age" : 4, "count" : 25 } } { "_id" : 5, "value" : { "age" : 5, "count" : 25 } } { "_id" : 6, "value" : { "age" : 6, "count" : 25 } } { "_id" : 7, "value" : { "age" : 7, "count" : 25 } } { "_id" : 8, "value" : { "age" : 8, "count" : 25 } } { "_id" : 9, "value" : { "age" : 9, "count" : 25 } } { "_id" : 10, "value" : { "age" : 10, "count" : 25 } } { "_id" : 11, "value" : { "age" : 11, "count" : 25 } } { "_id" : 12, "value" : { "age" : 12, "count" : 25 } } { "_id" : 13, "value" : { "age" : 13, "count" : 25 } } { "_id" : 14, "value" : { "age" : 14, "count" : 25 } } { "_id" : 15, "value" : { "age" : 15, "count" : 25 } } { "_id" : 16, "value" : { "age" : 16, "count" : 25 } } { "_id" : 17, "value" : { "age" : 17, "count" : 25 } } { "_id" : 18, "value" : { "age" : 18, "count" : 25 } } { "_id" : 19, "value" : { "age" : 19, "count" : 25 } } { "_id" : 20, "value" : { "age" : 20, "count" : 25 } } has more >
其他操作
> u = db.users.findOne({"im.qq":12345}) { "_id" : ObjectId("4e27dc01df0c628545d11eac"), "name" : "user1", "age" : 15, "address" : [ "address1", "address2" ], "im" : { "msn" : "user1@hotmail.com", "qq" : 12345 } } > u = db.users.find({"im.qq":{$exists:true}}, {"im.qq":1}) //可以通过 $exists 判断某个字段是否存在 { "_id" : ObjectId("4e27dc01df0c628545d11eac"), "im" : { "qq" : 12345 } } > db.users.insert({name:"user3", data:[1,2,3,4,5,6,7]}) > db.users.insert({name:"user4", data:[1,2,3]}) > db.users.find({data:{$all:[2,3,4]}}) //$all: 判断数组属性是否包含全部条件。 { "_id" : ObjectId("4e27dcc1df0c628545d11eae"), "name" : "user3", "data" : [ 1,2, 3, 4, 5, 6, 7 ] } 注意和 $in 的区别。$in 是检查目标属性值是条件表达式中的一员,而 $all 则要求属性值包含全部条件元素。 > db.users.find({data:{$size:3}})//$size: 匹配数组属性元素数量 { "_id" : ObjectId("4e27dcc6df0c628545d11eaf"), "name" : "user4", "data" : [ 1,2, 3 ] } > db.users.find({data:{$type:1}})//$type: 判断属性类型。 { "_id" : ObjectId("4e27dcc1df0c628545d11eae"), "name" : "user3", "data" : [ 1,2, 3, 4, 5, 6, 7 ] } { "_id" : ObjectId("4e27dcc6df0c628545d11eaf"), "name" : "user4", "data" : [ 1,2, 3 ] } double:1 string: 2 object: 3 array: 4 binary data: 5 object id: 7 boolean: 8 date: 9 null: 10 regular expression: 11 javascript code: 13 symbol: 14 javascript code with scope: 15 32-bit integer: 16 timestamp: 17 64-bit integer: 18 min key: 255 max key: 127 > db.users.find({name:/user[135]/i}, {name:1})//使用正则表达式进行查询。 { "_id" : ObjectId("4e27dcc1df0c628545d11eae"), "name" : "user3" } i: 忽略大小写。 m: 默认为单行处理,此标记表示多行。 x: 扩展。 > db.users.find({address:"abc"})//数组属性元素值匹配 { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "name" : "user1", "age" : 15, "address" : [ { "a" : 1 }, { "b" : 1 }, 3, "abc" ] } > db.users.find({address:{$elemMatch:{a:1, b:{$gt:5}}}}) //{data:"abc"} 仅简单匹配数组属性是否包含该元素。$elemMatch 则可以处理更复杂的元素查找条件。当然也可以写成如下方式。{elemMatch没有找出} //还可以直接使用序号进行操作 > db.users.find({"address.a":1, "address.b":{$gt:5}}) { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "name" : "user1", "age" : 15, "address" : [ { "a" : 1 }, { "b" : 10 }, 3, "abc" ] } > db.users.find({"address.2":3}) { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "name" : "user1", "age" : 15, "address" : [ { "a" : 1 }, { "b" : 10 }, 3, "abc" ] } > db.users.find({name:{$not:/user3/}}, {name:1})//$not: 取反,表示返回条件不成立的文档。 { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "name" : "user1" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb1"), "name" : "user0" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb2"), "name" : "user1" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "name" : "user2" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "name" : "user4" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb6"), "name" : "user5" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb7"), "name" : "user6" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb8"), "name" : "user7" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb9"), "name" : "user8" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eba"), "name" : "user9" } > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "name" : "user1", "age" : 15, "address" : [ { "a" : 1 }, { "b" : 10 }, 3, "abc" ] } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb2"), "name" : "user1", "age" : 21, "sex" : 1 } > db.users.update({name:"user1"}, {$unset:{address:1, im:1}})//$unset: 和 $set 相反,表示移除文档属性 > db.users.find({name:"user1"}) { "_id" : ObjectId("4e27de60df0c628545d11eb0"), "age" : 15, "name" : "user1" } { "_id" : ObjectId("4e27e1ebdf0c628545d11eb2"), "name" : "user1", "age" : 21, "sex" : 1 } > u = db.users.find({name:"user2"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "name" : "user2", "age" : 22, "sex" : 0 } > db.users.update({name:"user2"}, {$push:{data:1}}) //$push: 和 $ pushAll 都是向数组属性添加元素 > u = db.users.find({name:"user2"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "age" : 22, "data" : [ 1 ], "name" : "user2", "sex" : 0 } > db.users.update({name:"user2"}, {$pushAll:{data:[2,3,4,5]}}) > u = db.users.find({name:"user2"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "age" : 22, "data" : [ 1, 2, 3,4, 5 ], "name" : "user2", "sex" : 0 } > u = db.users.find({name:"user3"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb4"), "name" : "user3", "age" : 23, "sex" : 1 } > db.users.update({name:"user3"}, {$addToSet:{data:1}}) // $addToSet: 和 $push 类似,不过仅在该元素不存在时才添加 (Set 表示不重复元素集合) > u = db.users.find({name:"user3"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb4"), "age" : 23, "data" : [ 1 ], "name" : "user3", "sex" : 1 } > db.users.update({name:"user3"}, {$addToSet:{data:1}}) > u = db.users.find({name:"user3"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb4"), "age" : 23, "data" : [ 1 ], "name" : "user3", "sex" : 1 } > db.users.update({name:"user3"}, {$push:{data:1}}) > u = db.users.find({name:"user3"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb4"), "age" : 23, "data" : [ 1, 1 ], "name" : "user3", "sex" : 1 } > db.users.update({name:"user4"}, {$addToSet:{data:{$each:[1,2,3,4]}}})//要添加多个元素,使用 $each > u = db.users.find({name:"user4"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "age" : 24, "data" : [ 1, 2, 3,4 ], "name" : "user4", "sex" : 0 } > db.users.find({name:"user4"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "age" : 24, "data" : [ 1, 2, 3,4 ], "name" : "user4", "sex" : 0 } > db.users.update({name:"user4"}, {$pop:{data:1}}) //$pop: 移除数组属性的元素,$pull 按值移除,$pullAll 移除所有符合提交的元素 > db.users.find({name:"user4"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "age" : 24, "data" : [ 1, 2, 3 ], "name" : "user4", "sex" : 0 } > db.users.update({name:"user4"}, {$pop:{data:-1}}) > db.users.find({name:"user4"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "age" : 24, "data" : [ 2, 3 ], "name" : "user4", "sex" : 0 } > db.users.update({name:"user4"}, {$pull:{data:2}})//移除全部 2 > db.users.find({name:"user4"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb5"), "age" : 24, "data" : [ 3 ], "name" : "user4", "sex" : 0 } > db.users.find({name:"user2"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "age" : 22, "data" : [ 1, 2, 3,4, 5 ], "name" : "user2", "sex" : 0 } > db.users.update({name:"user2"}, {$pullAll:{data:[2,3,6]}}) > db.users.find({name:"user2"}) { "_id" : ObjectId("4e27e1ebdf0c628545d11eb3"), "age" : 22, "data" : [ 1, 4, 5 ], "name" : "user2", "sex" : 0 } > db.dropDatabase() { "dropped" : "company", "ok" : 1 } > for (var i = 0; i < 10; i++) db.users.insert({name:"user"+i, age:i}) > db.users.find()//$where: 用 JS 代码来代替有些丑陋的 $lt、$gt { "_id" : ObjectId("4e27e3b4df0c628545d11ebb"), "name" : "user0", "age" : 0 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebc"), "name" : "user1", "age" : 1 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebd"), "name" : "user2", "age" : 2 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebe"), "name" : "user3", "age" : 3 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebf"), "name" : "user4", "age" : 4 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec0"), "name" : "user5", "age" : 5 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec1"), "name" : "user6", "age" : 6 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec2"), "name" : "user7", "age" : 7 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec3"), "name" : "user8", "age" : 8 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec4"), "name" : "user9", "age" : 9 } > db.users.find({$where:"this.age > 7 || this.age < 3"}) { "_id" : ObjectId("4e27e3b4df0c628545d11ebb"), "name" : "user0", "age" : 0 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebc"), "name" : "user1", "age" : 1 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebd"), "name" : "user2", "age" : 2 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec3"), "name" : "user8", "age" : 8 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec4"), "name" : "user9", "age" : 9 } > db.users.find("this.age > 7 || this.age < 3") { "_id" : ObjectId("4e27e3b4df0c628545d11ebb"), "name" : "user0", "age" : 0 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebc"), "name" : "user1", "age" : 1 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebd"), "name" : "user2", "age" : 2 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec3"), "name" : "user8", "age" : 8 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec4"), "name" : "user9", "age" : 9 } > db.users.find({$where: function(){ return this.age > 7 || this.age < 3;}}) { "_id" : ObjectId("4e27e3b4df0c628545d11ebb"), "name" : "user0", "age" : 0 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebc"), "name" : "user1", "age" : 1 } { "_id" : ObjectId("4e27e3b4df0c628545d11ebd"), "name" : "user2", "age" : 2 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec3"), "name" : "user8", "age" : 8 } { "_id" : ObjectId("4e27e3b4df0c628545d11ec4"), "name" : "user9", "age" : 9 }
8:索引
> for (var i = 0; i < 30; i++) { ... u = { name : "user" + i, ... age : 20 + i, ... contact : { ... address : ["address1_" + i, "address2_" + i], ... postcode : 100000 + i, ... } ... }; ... db.users.insert(u); ... } //使用 ensureIndex 创建索引,dropIndex() 删除索引,dropIndexes() 删除全部索引(不包括 _id 等系统索引)。 > db.users.ensureIndex({name:1}) > db.users.ensureIndex({age:1}) > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 } } { "_id" : ObjectId("4c4a...b798"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1" } { "_id" : ObjectId("4c4a...b799"), "ns" : "blog.users", "key" : { "age" : 1 }, "name" : "age_1" } > db.users.dropIndex({age:1}) { "nIndexesWas" : 3, "ok" : true } > db.users.dropIndexes() { "nIndexesWas" : 2, "msg" : "non-_id indexes dropped for collection", "ok" : true } > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 } } //reIndex 则是重建索引 > db.users.ensureIndex({name:1}) > db.users.ensureIndex({age:1}) > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 } } { "_id" : ObjectId("4c4a...b82a"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1" } { "_id" : ObjectId("4c4a...b82b"), "ns" : "blog.users", "key" : { "age" : 1 }, "name" : "age_1" } > db.users.reIndex() { "nIndexesWas" : 3, "msg" : "indexes dropped for collection", "ok" : 1, "nIndexes" : 3, "indexes" : [ { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4c4a...b82a"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1" }, { "_id" : ObjectId("4c4a...b82b"), "ns" : "blog.users", "key" : { "age" : 1 }, "name" : "age_1" } ], "ok" : 1 } > db.users.dropIndexes() { "nIndexesWas" : 3, "msg" : "non-_id indexes dropped for collection", "ok" : true } //当系统已有大量数据时,创建索引就是个非常耗时的活,我们可以在后台执行。 > db.users.ensureIndex({name:1}, {backgroud:true}) > db.users.reIndex({backgroud:true}) { "nIndexesWas" : 2, "msg" : "indexes dropped for collection", "ok" : 1, "nIndexes" : 2, "indexes" : [ { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4c4a...b79c"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1", "backgroud" : true } ], "ok" : 1 } //MongoDB 提供了一个 explain 命令让我们获知系统如何处理查询请求。 > db.users.ensureIndex({name:1}) > db.users.ensureIndex({age:1}) > db.users.find({age:{$gt:45}}, {name:1, age:1}) { "_id" : ObjectId("4c4a8edeeb257107735eb826"), "name" : "user26", "age" : 46 } { "_id" : ObjectId("4c4a8edeeb257107735eb827"), "name" : "user27", "age" : 47 } { "_id" : ObjectId("4c4a8edeeb257107735eb828"), "name" : "user28", "age" : 48 } { "_id" : ObjectId("4c4a8edeeb257107735eb829"), "name" : "user29", "age" : 49 } > db.users.find({age:{$gt:45}}, {name:1, age:1}).explain() { "cursor" : "BtreeCursor age_1", "nscanned" : 5, "nscannedObjects" : 4, "n" : 4, "millis" : 0, "indexBounds" : [ [ { "age" : 45 }, { "age" : 1.7976931348623157e+308 } ] ] } cursor: 返回游标类型(BasicCursor 或 BtreeCursor)。 nscanned: 被扫描的文档数量。 n: 返回的文档数量。 millis: 耗时(毫秒)。 indexBounds: 所使用的索引。 //我们可以创建深层索引,甚至直接用文档(sub-document)作为索引键。 > db.users.ensureIndex({"contact.postcode":1}) > db.users.find({"contact.postcode":{$lt:100009}}, {name:1, "contact.postcode":1}) { "_id" : ObjectId("4c4a8edeeb257107735eb80c"), "name" : "user0", "contact" : { "postcode" : 100000 } } { "_id" : ObjectId("4c4a8edeeb257107735eb80d"), "name" : "user1", "contact" : { "postcode" : 100001 } } { "_id" : ObjectId("4c4a8edeeb257107735eb80e"), "name" : "user2", "contact" : { "postcode" : 100002 } } { "_id" : ObjectId("4c4a8edeeb257107735eb80f"), "name" : "user3", "contact" : { "postcode" : 100003 } } { "_id" : ObjectId("4c4a8edeeb257107735eb810"), "name" : "user4", "contact" : { "postcode" : 100004 } } { "_id" : ObjectId("4c4a8edeeb257107735eb811"), "name" : "user5", "contact" : { "postcode" : 100005 } } { "_id" : ObjectId("4c4a8edeeb257107735eb812"), "name" : "user6", "contact" : { "postcode" : 100006 } } { "_id" : ObjectId("4c4a8edeeb257107735eb813"), "name" : "user7", "contact" : { "postcode" : 100007 } } { "_id" : ObjectId("4c4a8edeeb257107735eb814"), "name" : "user8", "contact" : { "postcode" : 100008 } } > db.users.find({"contact.postcode":{$lt:100009}}, {name:1, "contact.postcode":1}).explain() { "cursor" : "BtreeCursor contact.postcode_1", "nscanned" : 10, "nscannedObjects" : 9, "n" : 9, "millis" : 0, "indexBounds" : [ [ { "contact.postcode" : -1.7976931348623157e+308 }, { "contact.postcode" : 100009 } ] ] } > db.users.dropIndex({"contact.postcode":1}) { "nIndexesWas" : 4, "ok" : 1 } > db.users.ensureIndex({contact:1}) > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 }, "v" : 0 } { "_id" : ObjectId("4e27eb604855eaada94c711f"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1", "backgroud" : true, "v" : 0 } { "_id" : ObjectId("4e27eb7c4855eaada94c7121"), "ns" : "blog.users", "key" : { "age" : 1 }, "name" : "age_1", "v" : 0 } { "_id" : ObjectId("4e27ebc64855eaada94c7123"), "ns" : "blog.users", "key" : { "contact" : 1 }, "name" : "contact_1", "v" : 0 } > db.users.find({contact:{postcode:{$lt:100009}}}).explain() { "cursor" : "BtreeCursor contact_1", "nscanned" : 0, "nscannedObjects" : 0, "n" : 0, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "contact" : [ [ { "postcode" : { "$lt" : 100009 } }, { "postcode" : { "$lt" : 100009 } } ] ] } } > db.users.find({"contact.postcode":{$lt:100009}}).explain() { "cursor" : "BasicCursor", "nscanned" : 30, "nscannedObjects" : 30, "n" : 9, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { } } > db.users.find({contact:{address:"address2_23"}}).explain() { "cursor" : "BtreeCursor contact_1", "nscanned" : 0, "nscannedObjects" : 0, "n" : 0, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "contact" : [ [ { "address" : "address2_23" }, { "address" : "address2_23" } ] ] } } > db.users.find({"contact.address":"address2_23"}).explain() { "cursor" : "BasicCursor", "nscanned" : 30, "nscannedObjects" : 30, "n" : 1, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { } } //创建复合索引也很简单 > db.users.ensureIndex({name:1, age:-1}) > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 }, "v" : 0 } { "_id" : ObjectId("4e27eb604855eaada94c711f"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1", "backgroud" : true, "v" : 0 } { "_id" : ObjectId("4e27eb7c4855eaada94c7121"), "ns" : "blog.users", "key" : { "age" : 1 }, "name" : "age_1", "v" : 0 } { "_id" : ObjectId("4e27ebc64855eaada94c7123"), "ns" : "blog.users", "key" : { "contact" : 1 }, "name" : "contact_1", "v" : 0 } { "_id" : ObjectId("4e27ec0a4855eaada94c7124"), "ns" : "blog.users", "key" : { "name" : 1, "age" : -1 }, "name" : "name_1_age_-1", "v" : 0 } > db.users.find({age:{$lt:25}, name:"user2"}, {name:1, age:1}) { "_id" : ObjectId("4e27eac34855eaada94c70fe"), "name" : "user2", "age" : 22 } > db.users.find({age:{$lt:25}, name:"user2"}, {name:1, age:1}).explain() { "cursor" : "BtreeCursor name_1_age_-1", "nscanned" : 1, "nscannedObjects" : 1, "n" : 1, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "name" : [ [ "user2", "user2" ] ], "age" : [ [ 25, -1.7976931348623157e+308 ] ] } } //复合索引同样可用于局部属性的搜索,但必须依照索引字段顺序。比如创建索引字段顺序 "a,b,c",那么仅对 "a,b,c"、"a,b"、"a" 查询有效,而对 "b,c" 之类的组合无效。 > db.users.dropIndex({name:1}) { "nIndexesWas" : 5, "ok" : 1 } > db.users.dropIndex({name:1}) { "errmsg" : "index not found", "ok" : 0 } > db.users.dropIndex({age:1}) { "nIndexesWas" : 4, "ok" : 1 } > db.users.dropIndex({contact:1}) { "nIndexesWas" : 3, "ok" : 1 } > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 }, "v" : 0 } { "_id" : ObjectId("4e27ec0a4855eaada94c7124"), "ns" : "blog.users", "key" : { "name" : 1, "age" : -1 }, "name" : "name_1_age_-1", "v" : 0 } > db.users.find({name:"user12"}).explain() { "cursor" : "BtreeCursor name_1_age_-1", "nscanned" : 1, "nscannedObjects" : 1, "n" : 1, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "name" : [ [ "user12", "user12" ] ], "age" : [ [ { "$maxElement" : 1 }, { "$minElement" : 1 } ] ] } } > db.users.find({age:18}).explain() { "cursor" : "BasicCursor", "nscanned" : 30, "nscannedObjects" : 30, "n" : 0, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { } } //只需在 ensureIndex 命令中指定 unique 即可创建唯一索引。 > db.users.ensureIndex({name:1}, {unique:true}) > db.system.indexes.find() { "name" : "_id_", "ns" : "blog.users", "key" : { "_id" : 1 }, "v" : 0 } { "_id" : ObjectId("4e27ec0a4855eaada94c7124"), "ns" : "blog.users", "key" : { "name" : 1, "age" : -1 }, "name" : "name_1_age_-1", "v" : 0 } { "_id" : ObjectId("4e27ec794855eaada94c7125"), "ns" : "blog.users", "key" : { "name" : 1 }, "name" : "name_1", "unique" : true, "v" : 0 } > db.users.insert({name:"user1"}) E11000 duplicate key error index: blog.users.$name_1 dup key: { : "user1" } //如果创建唯一索引前已经有重复文档,那么可以用 dropDups 删除多余的数据。 > db.users.dropIndexes() { "nIndexesWas" : 3, "msg" : "non-_id indexes dropped for collection", "ok" : 1 } > db.users.insert({name:"user1"}) > db.users.find({name:"user1"}, {name:1}) { "_id" : ObjectId("4e27eac34855eaada94c70fd"), "name" : "user1" } { "_id" : ObjectId("4e27ec9f4855eaada94c7127"), "name" : "user1" } > db.users.ensureIndex({name:1}, {unique:true, dropDups:true}) E11000 duplicate key error index: blog.users.$name_1 dup key: { : "user1" } > db.users.find({name:"user1"}, {name:1}) { "_id" : ObjectId("4e27eac34855eaada94c70fd"), "name" : "user1" } //对于数组类型属性,会自动索引全部数组元素 > db.users.dropIndexes() { "nIndexesWas" : 2, "msg" : "non-_id indexes dropped for collection", "ok" : 1 } > db.users.ensureIndex({"contact.address":1}) > db.users.find({"contact.address":"address2_13"}).explain() { "cursor" : "BtreeCursor contact.address_1", "nscanned" : 1, "nscannedObjects" : 1, "n" : 1, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : true, "indexOnly" : false, "indexBounds" : { "contact.address" : [ [ "address2_13", "address2_13" ] ] } } //hint 命令可以强制使用某个索引 > db.users.dropIndexes() { "nIndexesWas" : 2, "msg" : "non-_id indexes dropped for collection", "ok" : 1 } > db.users.ensureIndex({name:1, age:1}) > db.users.find({age:{$lt:30}}).explain() { "cursor" : "BasicCursor", "nscanned" : 30, "nscannedObjects" : 30, "n" : 10, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { } } > db.users.find({age:{$lt:30}}).hint({name:1, age:1}).explain() { "cursor" : "BtreeCursor name_1_age_1", "nscanned" : 30, "nscannedObjects" : 10, "n" : 10, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ], "age" : [ [ -1.7976931348623157e+308, 30 ] ] } } //MongoDB 会将索引数据载入内存,以提高查询速度。我们可以用 totalIndexSize 获取全部索引数据大小 > db.users.totalIndexSize() 16384
9:优化
//MongoDB 自带 Profiler,可以非常方便地记录下所有耗时过长操作,以便于调优。 > db.setProfilingLevel(n) n: 0: Off; 1: Log Slow Operations; 2: Log All Operations. 通常我们只关心 Slow Operation,Level 1 默认记录 >100ms 的操作,当然我们也可以自己调整 "db.setProfilingLevel(2, 300)"。 Profiler 信息保存在 system.profile (Capped Collection) 中。 > db.setProfilingLevel(1) { "was" : 1, "slowms" : 100, "ok" : 1 } > db.users.find().sort({age:-1}).limit(10000) { "_id" : ObjectId("4e27f34e256a7f5699394589"), "name" : "user2583248", "age" :2583268, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394588"), "name" : "user2583247", "age" :2583267, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394587"), "name" : "user2583246", "age" :2583266, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394586"), "name" : "user2583245", "age" :2583265, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394585"), "name" : "user2583244", "age" :2583264, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394584"), "name" : "user2583243", "age" :2583263, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394583"), "name" : "user2583242", "age" :2583262, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394582"), "name" : "user2583241", "age" :2583261, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394581"), "name" : "user2583240", "age" :2583260, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394580"), "name" : "user2583239", "age" :2583259, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f569939457f"), "name" : "user2583238", "age" :2583258, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f569939457e"), "name" : "user2583237", "age" :2583257, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f569939457d"), "name" : "user2583236", "age" :2583256, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f569939457c"), "name" : "user2583235", "age" :2583255, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f569939457b"), "name" : "user2583234", "age" :2583254, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f569939457a"), "name" : "user2583233", "age" :2583253, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394579"), "name" : "user2583232", "age" :2583252, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394578"), "name" : "user2583231", "age" :2583251, "sex" : 1 } { "_id" : ObjectId("4e27f34e256a7f5699394577"), "name" : "user2583230", "age" :2583250, "sex" : 0 } { "_id" : ObjectId("4e27f34e256a7f5699394576"), "name" : "user2583229", "age" :2583249, "sex" : 1 } has more > db.system.profile.find() { "ts" : ISODate("2011-07-21T09:36:42.515Z"), "info" : "insert blog.users 140ms", "millis" : 140 } { "ts" : ISODate("2011-07-21T09:38:54.198Z"), "info" : "query blog.users ntoreturn:10000 scanAndOrder reslen:700036 nscanned:2593249 \nquery: { query: {}, orderby: { age: -1.0 } } nreturned:10000 11781ms", "millis" : 11781 } ------------- ts: 操作执行时间。 info: 操作详细信息。 info.query: 查询目标(数据库.集合)。 info.ntoreturn: 客户端期望返回的文档数量。 info.nscanned: 服务器实际扫描的文档数量。 info.reslen: 查询结果字节长度。 info.nreturnned: 查询返回文档数。 millis: 操作耗时(毫秒)。 备注 如果 nscanned 远大于 nreturned,那么需要使用索引。 如果 reslen 返回字节非常大,那么考虑只获取所需的字段。 执行 update 操作时同样检查一下 nscanned,并使用索引减少文档扫描数量。 使用 db.eval() 在服务端执行某些统计操作。 减少返回文档数量,使用 skip & limit 分页。 ----------- > db.users.find().sort({age:-1}).limit(10000).explain() { "cursor" : "BasicCursor", "nscanned" : 2593249, "nscannedObjects" : 2593249, "n" : 10000, "scanAndOrder" : true, "millis" : 11781, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { } } >
10:Master-Slaver
单Master
配置 mongod --logpath E:\mongodb\shard\master\db\log.txt --port 10001 --dbpath E:\mongodb\shard\master\db --master mongod --logpath E:\mongodb\shard\slave\db\log.txt --port 10002 --dbpath E:\mongodb\shard\slave\db -slave --source 10.53.139.138:10001 --autoresync //autoresync 参数会在系统发生意外情况造成主从数据不同步时,自动启动复制操作 (同步复制 10 分钟内仅执行一次)。除此之外,还可以用 --slavedelay 设定更新频率(秒)。 Master E:\mongodb\shard\master>mongo --port 10001 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10001/test > db.isMaster() { "ismaster" : true, "maxBsonObjectSize" : 16777216, "ok" : 1 } > db.printReplicationInfo() configured oplog size: 47.6837158203125MB log length start to end: 74secs (0.02hrs) oplog first event time: Fri Jul 22 2011 14:30:32 GMT+0800 oplog last event time: Fri Jul 22 2011 14:31:46 GMT+0800 now: Fri Jul 22 2011 14:31:49 GMT+0800 > use blog switched to db blog > db.users.insert({name:"user", age:20, sex:1}) > db.users.find() { "_id" : ObjectId("4e291b52e742b344d4d84ead"), "name" : "user", "age" : 20, "sex" : 1 } Slaver E:\mongodb\shard\master>mongo --port 10002 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10002/test > db.isMaster() { "ismaster" : false, "maxBsonObjectSize" : 16777216, "ok" : 1 } > db.printSlaveReplicationInfo() source: 10.53.139.138:10001 syncedTo: Fri Jul 22 2011 14:32:16 GMT+0800 = 16secs ago (0hrs) > use local switched to db local > db.sources.find() { "_id" : ObjectId("4e29192760dea574d7e171ae"), "host" : "10.53.139.138:10001", "source" : "main", "syncedTo" : { "t" : 1311316386000, "i" : 1 }, "localLogTs" : { "t" : 0, "i" : 0 } } > use blog switched to db blog > db.users.find() { "_id" : ObjectId("4e291b52e742b344d4d84ead"), "name" : "user", "age" : 20, "sex" : 1 } > db.users.insert({name:"user1", age:21, sex:0}) not master
多Master
配置 mongod --logpath E:\mongodb\shard\master\db\log.txt --port 10001 --dbpath E:\mongodb\shard\master\db --master mongod --logpath E:\mongodb\shard\master1\db\log.txt --port 10002 --dbpath E:\mongodb\shard\master1\db --master mongod --logpath E:\mongodb\shard\slave\db\log.txt --port 10003 --dbpath E:\mongodb\shard\slave\db -slave 连接slaver添加主服务器 E:\mongodb\shard\slave>mongo --port 10003 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10003/test > use local switched to db local > db.sources.insert({host:"10.53.139.138:10001"}) > db.sources.insert({host:"10.53.139.138:10002"}) > db.printSlaveReplicationInfo() source: 10.53.139.138:10001 doing initial sync source: 10.53.139.138:10002 doing initial sync master1添加数据 E:\mongodb\shard\slave>mongo --port 10001 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10001/test > use db1 switched to db db1 > db.users.insert({name:"user1"}) > db.users.find() { "_id" : ObjectId("4e291eaa8abc2b0f77aade99"), "name" : "user1" } master2添加 E:\mongodb\shard\slave>mongo --port 10002 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10002/test > use db2 switched to db db2 > db.users.insert({name:"user2"}) > db.users.find() { "_id" : ObjectId("4e291ee418179745d0094f33"), "name" : "user2" } 连接slaver E:\mongodb\shard\slave>mongo --port 10003 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10003/test > use db1 switched to db db1 > db.users.find() { "_id" : ObjectId("4e291eaa8abc2b0f77aade99"), "name" : "user1" } > use db2 switched to db db2 > db.users.find() { "_id" : ObjectId("4e291ee418179745d0094f33"), "name" : "user2" }
11:Shard
shard0:mongod --shardsvr --port 27020 --dbpath E:\mongodb\shard\shard1\db\ shard1:mongod --shardsvr --dbpath E:\mongodb\shard\shard2\db\ --port 27021 config:mongod --configsvr --dbpath E:\mongodb\shard\Config\db\ --port 27022 连接config下 mongos --configdb 10.53.139.138:27022 mongo --port 27017 use admin db.runCommand({addshard:"10.53.139.138:27020",name:"shard0"}) db.runCommand({addshard:"10.53.139.138:27021",name:"shard1"}) db.runCommand({listshards:1}) db.runCommand({enablesharding:"test"}) db.runCommand({shardcollection:"test.people",key:{id:1}}) use test show collections db.people.stats() for (var i = 1; i <= 200003; i++) db.people.save({id:i,value1:"1234567890",value2:"1234567890",value3:"1234567890",value4:"1234567890"})
12:故障转移(Replication)
配置set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\1\log.txt --dbpath E:\mongodb\shard\shard1\1\db --port 10001 --nohttpinterface --replSet set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\2\log.txt --dbpath E:\mongodb\shard\shard1\2\db --port 10002 --nohttpinterface --replSet set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\3\log.txt --dbpath E:\mongodb\shard\shard1\3\db --port 10003 --nohttpinterface --replSet set1 E:\mongodb\shard\shard1\1>mongo --port 10001 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10001/test >cfg = { _id: "set1", members: [ ... { _id:0, host:"10.53.139.138:10001" }, ... { _id:1, host:"10.53.139.138:10002" }, ... { _id:2, host:"10.53.139.138:10003" } ... ]} > rs.initiate(cfg) { "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } > rs.conf() { "_id" : "set1", "version" : 1, "members" : [ { "_id" : 0, "host" : "localhost:27017" }, { "_id" : 1, "host" : "localhost:27018" }, { "_id" : 2, "host" : "localhost:27019" } ] } > rs.status() { "set" : "set1", "date" : "Sat Aug 21 2010 15:21:13 GMT+0800 (CST)", "myState" : 2, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 1, "state" : 2, "stateStr" : "PRIMARY", "uptime" : 363, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:00:56Z") }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "self" : true }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 1, "stateStr" : "SECONDARY", "uptime" : 802, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:00:57Z") } ], "ok" : 1 } //暂停10001 set1:SECONDARY> rs.status() { "set" : "set1", "date" : ISODate("2011-07-22T06:01:11Z"), "myState" : 2, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 0, "state" : 1, "uptime" : 0, "lastHeartbeat" : "Sat Aug 21 2010 15:40:14 GMT+0800 (CST)", "errmsg" : "connect/transport error" }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "self" : true }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 816, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:01:11Z") } ], "ok" : 1 } //开启10001 set1:SECONDARY> rs.status() { "set" : "set1", "date" : ISODate("2011-07-22T06:01:43Z"), "myState" : 2, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 409, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:01:42Z") }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "self" : true }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 848, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:01:43Z") } ], "ok" : 1 } set1:SECONDARY> exit bye //准备10004 E:\mongodb\shard\shard1\1>mongo --port 10001 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10001/test set1:SECONDARY> rs.status() { "set" : "set1", "date" : ISODate("2011-07-22T06:02:26Z"), "myState" : 2, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "self" : true }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 454, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:02:24Z") }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 454, "optime" : { "t" : 1311313830000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T05:50:30Z"), "lastHeartbeat" : ISODate("2011-07-22T06:02:24Z") } ], "ok" : 1 } //非PRIMARY不能动态添加节点 set1:SECONDARY> rs.add("10.53.139.138:10004") { "errmsg" : "replSetReconfig command must be sent to the current replica set primary.", "ok" : 0 } set1:SECONDARY> exit bye E:\mongodb\shard\shard1\1>mongo --port 10003 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10003/test set1:PRIMARY> rs.add("10.53.139.138:10004") Fri Jul 22 14:03:24 DBClientCursor::init call() failed Fri Jul 22 14:03:24 query failed : admin.$cmd { replSetReconfig: { _id: "set1",version: 2, members: [ { _id: 0, host: "10.53.139.138:10001" }, { _id: 1, host: "10.53.139.138:10002" }, { _id: 2, host: "10.53.139.138:10003" }, { _id: 3.0, host: "10.53.139.138:10004" } ] } } to: 127.0.0.1:10003 shell got exception during reconfig: Error: error doing query: failed in some circumstances, the primary steps down and closes connections on a reconf ig null Fri Jul 22 14:03:24 trying reconnect to 127.0.0.1:10003 Fri Jul 22 14:03:24 reconnect 127.0.0.1:10003 ok set1:PRIMARY> rs.status() { "set" : "set1", "date" : ISODate("2011-07-22T06:03:50Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 24, "optime" : { "t" : 1311314604000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T06:03:24Z"), "lastHeartbeat" : ISODate("2011-07-22T06:03:48Z") }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 24, "optime" : { "t" : 1311314604000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T06:03:24Z"), "lastHeartbeat" : ISODate("2011-07-22T06:03:48Z") }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "optime" : { "t" : 1311314604000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T06:03:24Z"), "self" : true }, { "_id" : 3, "name" : "10.53.139.138:10004", "health" : 1, "state" : 3, "stateStr" : "RECOVERING", //新增加的节点 正在恢复数据 完成后为 SECONDARY "uptime" : 20, "optime" : { "t" : 1311314604000, "i" : 1 }, "optimeDate" : ISODate("2011-07-22T06:03:24Z"), "lastHeartbeat" : ISODate("2011-07-22T06:03:48Z"), "errmsg" : "initial sync done" } ], "ok" : 1 } set1:PRIMARY> exit bye //连接新加入的10004 E:\mongodb\shard\shard1\1>mongo --port 10004 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10004/test set1:SECONDARY> db.users.find() error: { "$err" : "not master and slaveok=false", "code" : 13435 } set1:SECONDARY>
13:集群方案
Set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\1\log.txt --dbpath E:\mongodb\shard\shard1\1\db --port 10001 --nohttpinterface --replSet set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\2\log.txt --dbpath E:\mongodb\shard\shard1\2\db --port 10002 --nohttpinterface --replSet set1 mongod --shardsvr --logpath E:\mongodb\shard\shard1\3\log.txt --dbpath E:\mongodb\shard\shard1\3\db --port 10003 --nohttpinterface --replSet set1 配置 E:\mongodb\shard\shard1\1>mongo --port 10001 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10001/test > cfg = { _id:'set1', members:[ ... ... { _id:0, host:'10.53.139.138:10001' }, ... ... { _id:1, host:'10.53.139.138:10002' }, ... ... { _id:2, host:'10.53.139.138:10003' } ... ... ]}; { "_id" : "set1", "members" : [ { "_id" : 0, "host" : "10.53.139.138:10001" }, { "_id" : 1, "host" : "10.53.139.138:10002" }, { "_id" : 2, "host" : "10.53.139.138:10003" } ] } > rs.initiate(cfg) { "info" : "Config now saved locally. Should come online in about a minut e.", "ok" : 1 } > rs.status() { "set" : "set1", "date" : ISODate("2011-07-21T10:14:08Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10001", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "optime" : { "t" : 1311243232000, "i" : 1 }, "optimeDate" : ISODate("2011-07-21T10:13:52Z"), "self" : true }, { "_id" : 1, "name" : "10.53.139.138:10002", "health" : 0, "state" : 6, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "t" : 0, "i" : 0 }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2011-07-21T10:14:07Z"), "errmsg" : "still initializing" }, { "_id" : 2, "name" : "10.53.139.138:10003", "health" : 1, "state" : 3, "stateStr" : "RECOVERING", "uptime" : 5, "optime" : { "t" : 0, "i" : 0 }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2011-07-21T10:14:07Z"), "errmsg" : "initial sync need a member to be primary or secondary to do our initial sync" } ], "ok" : 1 } set1:PRIMARY> exit bye set2 mongod --shardsvr --logpath E:\mongodb\shard\shard2\1\log.txt --dbpath E:\mongodb\shard\shard2\1\db --port 10011 --nohttpinterface --replSet set2 mongod --shardsvr --logpath E:\mongodb\shard\shard2\2\log.txt --dbpath E:\mongodb\shard\shard2\2\db --port 10012 --nohttpinterface --replSet set2 mongod --shardsvr --logpath E:\mongodb\shard\shard2\3\log.txt --dbpath E:\mongodb\shard\shard2\3\db --port 10013 --nohttpinterface --replSet set2 配置set2 E:\mongodb\shard\shard2\1>mongo --port 10011 MongoDB shell version: 1.8.2 connecting to: 127.0.0.1:10011/test > cfg = { _id:'set1', members:[ ... ... { _id:0, host:'10.53.139.138:10011' }, ... ... { _id:1, host:'10.53.139.138:10012' }, ... ... { _id:2, host:'10.53.139.138:10013' } ... ... ]}; { "_id" : "set1", "members" : [ { "_id" : 0, "host" : "10.53.139.138:10011" }, { "_id" : 1, "host" : "10.53.139.138:10012" }, { "_id" : 2, "host" : "10.53.139.138:10013" } ] } > cfg = { _id:'set2', members:[ ... ... { _id:0, host:'10.53.139.138:10011' }, ... ... { _id:1, host:'10.53.139.138:10012' }, ... ... { _id:2, host:'10.53.139.138:10013' } ... ... ]}; { "_id" : "set2", "members" : [ { "_id" : 0, "host" : "10.53.139.138:10011" }, { "_id" : 1, "host" : "10.53.139.138:10012" }, { "_id" : 2, "host" : "10.53.139.138:10013" } ] } > rs.initiate(cfg) { "info" : "Config now saved locally. Should come online in about a minut e.", "ok" : 1 } > rs.status() { "set" : "set2", "date" : ISODate("2011-07-21T10:19:33Z"), "myState" : 2, "members" : [ { "_id" : 0, "name" : "10.53.139.138:10011", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "optime" : { "t" : 1311243565000, "i" : 1 }, "optimeDate" : ISODate("2011-07-21T10:19:25Z"), "self" : true }, { "_id" : 1, "name" : "10.53.139.138:10012", "health" : 0, "state" : 6, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "t" : 0, "i" : 0 }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2011-07-21T10:19:32Z"), "errmsg" : "still initializing" }, { "_id" : 2, "name" : "10.53.139.138:10013", "health" : 0, "state" : 6, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "t" : 0, "i" : 0 }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2011-07-21T10:19:32Z"), "errmsg" : "still initializing" } ], "ok" : 1 } set2:SECONDARY> exit bye 配置configserver mongod --configsvr --logpath E:\mongodb\shard\Config\1\log.txt --dbpath E:\mongodb\shard\Config\1\db --port 20000 --nohttpinterface mongod --configsvr --logpath E:\mongodb\shard\Config\2\log.txt --dbpath E:\mongodb\shard\Config\2\db --port 20001 --nohttpinterface mongod --configsvr --logpath E:\mongodb\shard\Config\3\log.txt --dbpath E:\mongodb\shard\Config\3\db --port 20002 --nohttpinterface 启动routserver mongos --logpath E:\mongodb\shard\rout\log.txt --configdb 10.53.139.138:20000,10.53.139.138:20001,10.53.139.138:20002 配置分片 E:\mongodb\shard\shard2\1>cd E:\mongodb\shard\rout E:\mongodb\shard\rout>mongo MongoDB shell version: 1.8.2 connecting to: test > use admin switched to db admin > db.runCommand({ addshard:'set1/10.53.139.138:10001,10.53.139.138:10002,10.53.1 39.138:10003' }) { "shardAdded" : "set1", "ok" : 1 } > db.runCommand({ addshard:'set2/10.53.139.138:10011,10.53.139.138:10012,10.53.1 39.138:10013' }) { "shardAdded" : "set2", "ok" : 1 } > db.runCommand({ shardcollection:'test.data', key:{_id:1} }) { "ok" : 0, "errmsg" : "sharding not enabled for db" } > db.runCommand({ shardcollection:'test.data', key:{_id:1} }) { "ok" : 0, "errmsg" : "sharding not enabled for db" } > db.runCommand({ listshards:1 }) { "shards" : [ { "_id" : "set1", "host" : "set1/10.53.139.138:10001,10.53.139.138:10002,1 0.53.139.138:10003" }, { "_id" : "set2", "host" : "set2/10.53.139.138:10011,10.53.139.138:10012,1 0.53.139.138:10013" } ], "ok" : 1 } > printShardingStatus() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 3 } shards: { "_id" : "set1", "host" : "set1/10.53.139.138:10001,10.53.139.138:10002,10.53.139.138:100 03" } { "_id" : "set2", "host" : "set2/10.53.139.138:10011,10.53.139.138:10012,10.53.139.138:100 13" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "set1" } 简单测试 > use test switched to db test > db.data.insert({name:1}) > db.data.insert({name:2}) > db.data.insert({name:3}) > db.data.find() { "_id" : ObjectId("4e28015cbb9f26c67deacec6"), "name" : 1 } { "_id" : ObjectId("4e28015ebb9f26c67deacec7"), "name" : 2 } { "_id" : ObjectId("4e280160bb9f26c67deacec8"), "name" : 3 }