一、简介和安装 ./bin/mongod --dbpath /path/to/database --logpath /path/to/log --fork --port 27017 mongodb非常的占磁盘空间, 刚启动后要占3-4G左右,--smallfiles 二、基本命令 1、登录mongodb client /use/local/mongo 2、查看当前数据库 show databases; show dbs; 两个可能 3、admin是和管理有关的库,local 是放schema有关的内容,不要乱动 4、切换到数据库 use admin; show tables; 或者 show collections; admin下的表不要随便操作。 5、db help查看数据库操作帮助命令 6、创建数据库:mongo是隐式创建 use shop; 7、创建表[集合] db.createcollection('user'); 8、show dbs; 9、查看表[集合] show collections 10、插入数据 db.user.insert({name:lisi,age:22}); 11、查看数据:db.user.find(); 12、db.user.insert(id:3,name:'hmm',hoby:['basketball','fottball'],intro:{title:'my intro'}); 13、collection也是不用显示创建的 14、db.goods.insert(_id:1,name:'n1',price:133); 由此可见不用显示创建collection 15、删除collection db.user.drop();//删除集合user 16、db.dropDatabase();//删除database; 三、CRUD操作 1、增加单篇文档 db.stu.insert({sn:001,name,'xiaoming'}); 覆盖默认ID db.stu.insert({_id:002,sn:002,name:'lisi'}); 2、批量插入 db.stu.insert({_id:3,sn:003,name:guangyu},{_id:4,sn:004,name:zhangwei}); 3、插入无限制深度的文档 db.stu.insert({name:x:'li',m:'shimin'},{jli:'xxx'}) 4、删除 db.stu.remove({sn:001}); 删除sn为001的文档 5、删除全部 db.stu.remove(); 6、查询表达式是json对象 7、继续删除 db.stu.remove(gender:'m'); db.stu.remove(gender:'m',true); true限制只能删除一行 8、错误的修改 db.stu.update({name:'zhangsan'},{name:'lisi'}); 前一个表达式为想要修改的操作,后一个表达式表示要改成什么样。这个修改有问题,新文档直接替换旧文档,其他属性都不见了。 9、正确的修改 db.stu.update({name:'poxi'},{$set:{name:'yanpoxi'}}); $set 修改 $unset 重设 1-->true 0-->false $rename 重命名 $inc 增长 db.stu.update( {name:'wukong'}, { $set:{name:'douzhanshengfo'}, $unset:{jinggu:1}, $rename:{set:gender}, $inc:{age:2} } ); 10、multi 修改多行 db.stu.update({ {gender:'m'}, {gender:'male'}, {multi:1} }) multiple表示可修改多行,不加只能修改匹配多行中的一行 11、upsert $setonInsert db.stu.update( {name:'wuyong'}, {$set:{name:'junshiwuyong'}} ); 如果没有wuyong这个人,那么将不做任何修改 db.stu.update( {name:'wuyong'}, {$set:{name:'junshiwuyong'}}, {upsert:true} ); 如果添加upsert为true,那么自动插入 但是这还是有问题,原来的字段会丢失 这个时候需要upsert的setOnInsert db.stu.update( {name:'wuyong'}, {$set:{name:'junshiwuyong'}}, {upsert:true}, {$setOnInsert:{gender:'male'}}//加上原来的字段 ); 12、查询 查询所有文档所有内容 db.stu.find(); 查询所有文档的gender属性 db.stu.find({},{gender:1}) 查询所有文档的gender属性,且不查询_id属性 db.stu.find({},{gender:1,_id:0}) 四:深入查询表达式 1: 最简单的查询表达式 {filed:value} ,是指查询field列的值为value的文档 2: $ne --- != 查询表达式 {field:{$nq:value}} 作用--查filed列的值 不等于 value 的文档 $gt--大于 $lt--小于 $lte小于等于 $gte大于等于 3: $nin --> not in { $nin [{cat_id:{$ne:30}}, {cat_id:{$eq:300}} ] } 4: $all 语法: {field:{$all:[v1,v2..]}} 是指取出 field列是一个数组,且至少包含 v1,v2值 5、$or $and { $and: [{shop_price:{$gte:30}}, {shop_price:{$lte:300}} ] } { $or [{shop_price:{$ne:30}}, {shop_price:{$eq:300}} ] } 6: $nor, {$nor,[条件1,条件2]} 是指 所有条件都不满足的文档为真返回 7、取模 $mod { goods_id:{$mode:[5,0]}, }, { goods_id:1, goods_name:1, _id:0 } 8、$exists 存在某一列则查出来 { age:{$exists:1} }, { goods_id:1, goods_name:1, _id:0 } 9、$type 按类型查询 { age:{$type:2} } 10、$where 例: db.goods.find ({$where:'this.cat_id != 3 && this.cat_id != 11'}); 直接将二进制数据转换为对象,对象的任何属性都可以导航得到、效率极低。不建议使用,好处是表达式可以写得很复杂和灵活 11、用正则表达式查询 以”诺基亚”开头的商品 例:db.goods.find({goods_name:/诺基亚.*/},{goods_name:1}); 四、游标操作 > var mycursor = db.bar.find({_id:{$lte:5}}) > while(mycursor.hasNext()) { ... printjson(mycursor.next()); ... } 五、用户管理 六、导入导出 七、副本集 如果主服务器自动关掉 rs.shutdownServer(); 会自动切换到别的服务器作为主服务器 编写mongo副本集的自动化安装脚本:参考mongo副本集安装脚本.sh 八、分片 分片配置 1、启动两台mongo服务器 mkdir -p /home/m17 /home/m18 /home/m20 /home/m30 /home/mlog mongd --dbpath /home/m17 --logpath /home/mlog/m17.log --fork --port 27017 mongd --dbpath /home/m18 --logpath /home/mlog/m18.log --fork --port 27018 2、配置configserver,管理meta信息 mongd --dbpath /home/m20 --logpath /home/mlog/m20.log --fork --port 27020 --configserver 3、配置一台mongo路由 mongos --logpath /home/mlog/m30.log --port 30000 --configdb 192.168.1.202:27020 --fork 4、连接路由 mongo --port 30000 5、在路由节点增加片节点 sh.addShard('192.168.10.202:27017') sh.addShard('192.168.10.202:27018') 6、在路由节点查看路由状态,发现路由片节点信息 sh.status(); 7、在路由节点插入数据 8、路由节点有数据,发现17有数据,18没有数据。因为没有加入路由规则的原因 9、sh.status 可以看到数据库,分区false,优先被放在shard0000 10、针对数据库启用分片 sh.enableShard('shard'); 11、sh.status 可以看到数据库shop,分区false,优先被放在shard0000 12、添加分片的表 sh.shardCollection(‘shop.goods’,{good_id:1}); 将good_id作为片键 13、查看sh.status,可以看到现实目前分片信息先落在shard0001 14、插入3W条数据 15、查看sh.status ,看到数据都落在shard0001上 16、再插入10W条数据,看到数据还是都落在shard0001上 17、上面疑问的原因如下: mongodb不是从单篇文档的级别,绝对平均的散落在各个片上, 而是N篇文档,形成一个块"chunk", 优先放在某个片上, 当这片上的chunk,比另一个片的chunk,区别比较大时, (>=3) ,会把本片上的chunk,移到另一个片上, 以chunk为单位, 维护片之间的数据均衡 问: 为什么插入了10万条数据,才2个chunk? 答: 说明chunk比较大(默认是64M) 在config数据库中,修改chunksize的值. 问: 既然优先往某个片上插入,当chunk失衡时,再移动chunk, 自然,随着数据的增多,shard的实例之间,有chunk来回移动的现象,这将带来什么问题? 答: 服务器之间IO的增加, 接上问: 能否我定义一个规则, 某N条数据形成1个块,预告分配M个chunk, M个chunk预告分配在不同片上. 以后的数据直接入各自预分配好的chunk,不再来回移动? 答: 能, 手动预先分片! 18、在config数据库,修改chunk use config; show tables; db.settings.find(); db.settings.save({_id:chunksize},{$set:{value:1}}) 19、查看分片信息 sh.status(); 20、继续插入更多数据15W吧 50W也可以的 21、查看分片信息 sh.status(); 22、可以看到两台片节点的分片数量大致平衡 手动预先分片: 1、对shop库下的user表分片,片键为userid sh.shardingCollection('shop.user',{userid:1}) 2、sh.status(); 3、模拟:40个块每个块1000条数据 4、定义规则 for(var i = 1;i<=40;i++){ sh.splitAt('shop.user',{userid:i*1000}); } 这样将会有40个chunk,这些chunk会平均分布到各节点上,这样插入的时候就不会产生chunk频繁移动的现象了 5、快速查看分片信息 sh.status(); 6、插入4W条数据 for(var i = 0;i<40000;i++){ db.user.insert({userid:i,name:'nnnn hello'}); } 7、查看两个分片节点的总数据,各2W条数据 九、分片和副本集配合 B--configserver C--副本集 D--副本集 1、分别创建副本集C、D,利用脚本自动化创建 2、副本集C,D可以认为是一台机器,将分片节点设置到C、D的主节点即可 3、配置configserver,管理meta信息 mongd --dbpath /home/m20 --logpath /home/mlog/m20.log --fork --port 27020 --configsvr 4、配置一台mongo路由 mongos --logpath /home/mlog/m30.log --port 30000 --configdb 192.168.1.202:27020 --fork 5、在路由节点增加片节点 sh.addShard('rs3/192.168.10.203:27017')#假设203的27017就是C的主节点 sh.addShard('rs4/192.168.10.203:27018')#假设203的27017就是D的主节点 6、添加需要分片的库 sh.enableSharding('shop'); 7、添加需要分片的表 sh.shardCollection('shop.user',{userid:1}); 8、手动分片测试 sh.splitAt('shop.user',{userid:1000})#1千条数据拆分一下 sh.splitAt('shop.user',{userid:2000})#两千条数据后拆分一下 sh.splitAt('shop.user',{userid:3000})#3千条数据后拆分一下 9、插入数据 for(var i = 0;i<4000;i++){ db.user.insert({ userid:i,intro:'i am lili'}); } 10、查看两个副本集的数据量 包括主节点和从节点 11、移除某个分片 use admin db.runCommand({removeShard:"rs2"}) 12、查询分片上的信息 sh.status(); 可以看到被移除分片的数据移动到别的分片上 并且被移除分片被标记上"draining" : true 13、将移除的分片恢复 db.shards.update({"_id" : "rs2"},{$unset:{draining:true}}, false, true) 可以看到分片的数据移动到恢复的分片的上 14、 十、网址转换项目 1、功能说明 *输入网址 *点击变短 *生成比较短的网址 *如果已经存在短网址,提示已经存在 *需要存储数据 原网址 短网址 2、短网址生成 3、PHP连接mongodb编译扩展