一、简介和安装
./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编译扩展