1、安装服务
(1)下载 Download MongoDB Community Server | MongoDB
(2) 解压,在管理员权限的cmd中
(3) 在随意的文件夹文件下建立一个data文件夹和一个log文件夹和log.txt文件
(4)安装服务 mongod --dbpath=d:/mongo/data/ --logpath=d:/mongo/log/log.txt --install --serviceName "MongoDB"
2、卸载服务
(1) 关闭mongodb服务,在管理员权限的cmd中
(2)卸载服务 mongod --dbpath=d:/mongo/data/ --logpath=d:/mongo/log/log.txt --remove
3、账号权限
账号:
(1)'root:root' 管理员账号(只能在admin数据库) 可读可写
(2)'test1:1234' 普通账号(test1数据库) 只可读不可写
(3)'test2:5678' 普通账号(test2数据库) 可读可写
权限说明:
管理员账号:可操作全部数据库
普通账号: 只能操作本身数据库
账号设置的顺序:
1、必须先设置root管理员账号
2、其次在设置普通账号test1和test
低版本mongo创建账号指令:
db.addUser(username,password [,readOnly=false])
db.addUser(username,password,true(只读))
db.addUser(username,password,false(可读可写))
3、关闭服务
4、卸载服务
5、使用管理员权限 重新安装服务,需要加上--auth权限参数,进行重新加入服务,重新启动mongodb服务
注意:权限登录,需先在选择的数据库下进行操作
mongodb用户角色:
read、readWrite、dbAdmin、userAdmin、clusterAdmin、readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
show databases/dbs ---查看所有数据库
use 数据库名 ---有,切换数据库;没有,创建数据库
show tables/collections ---查看所有表(集合)
db.getName() ---获取当前数据库
db.status() ---查看数据库状态
db.product.drop() ---删除表
写入数据:
mongoDB数据格式为Bson,类json格式
示例:db.product.insert({name:'huawei01',price:1000,weight:135,number:35})
插入多条:db.product.insert([{name:'huawei01',price:1000,weight:135,number:35},{name:'huawei02',price:1305,weight:123,number:60}])
数组信息添加:db.product.insert({name:'xiaomi',price:2000,weight:150,number:260,area:{province:'北京',city:'北京'},color:['red','white','blank']})
查询数据:
db.product.find() ---查询数据表的全部数据
db.product.findOne() ---查询数据表的第一条数据
db.product.find({name:'huawei01'}) ---查询name='huawei01'的记录信息
范围查询:
$ne => 不等于
例:db.product.find({price:{'$nt':1005}}) ---商品价格不等于1005的商品
$in => in $nin => not in
例:db.product.find({price:{'$in':[100,200]}}) ---商品价格等于100或者等于200的商品
$and
例:db.product.find({$and:[{price:{$get:100}},{price:{$lte:500}}]}) ---商品价格大于等于100并且小于等于500
$mod => 求模
例:db.product.find({price:{$mod:[5,0]}}) ---取价格求模余0的商品
$gt => 大于 $lt => 小于 $gte => 大于等于 $lte => 小于等于
例:db.product.find({price:{'$gt':1005}}) ---商品价格大于1005的商品
例:db.product.find({price:{'$gt':1000},weight:{'$lt':100}}) ---商品价格大于1000并且重量小于100的商品
例: db.product.find({price:1000,weight:{'$lt':100}}) ---商品价格等于1000并且重量小于100的商品
多维字段(子文档)的查询:
db.表.find({'key.name':值})
db.表.find({'key.name':{'$gt':值}})
db.表.find({'key.name':{'$gt':值},'key2.name2':{'$lt':值}})
数组条件的查询:
db.表.find({字段(数组):val}) ---数组元素值,有val即可(存在一个元素)
示例:db.product.find({color:'red'})
db.表.find({字段(数组):{'$all':[v1,v2]}}) ---数组元素值,存在v1和v2即可(存在的顺序不做要求)(存在多个元素)
示例:db.product.find({color:{'$all':['red','blank']}})
$or查询,多个条件,满足其一即可
示例:db.product.find({'$or':[{price:1000},{weight:{'$gte':150}}]})
限制查询字段:1:显示 0:排除
注意:设置限制时要输出就全部输出,要不输出就全部不输出。_id除外。可以随意设置0或1
db.表.find({条件},{字段1:1/0,字段2:1/0,.....})
示例:db.product.find({'$or':[{price:1000},{weight:{'$gte':150}}]},{name:1,price:1,weight:1,_id:0})
修改数据:
db.表.update({条件},{'$set':{字段:值,字段:值,......}})
示例:db.product.update({name:'xiaomi'},{'$set':{price:3000}})
db.表.update({条件},{字段:值,字段:值,......})
1、有$set的修改:只修改设置的字段,其他字段不变化
2、没有$set的修改:只修改设置的字段,没有修改的字段就删除了(除开_id字段)
3、字段有则直接修改,没有则添加为新字段
db.表.update({条件},{'$set':{字段:值,字段:值,......}},Option)
Option的作用:{upsert:true/false,multi:true/false}
upsert : 是指没有匹配的行,则直接插入该行
multi:是指修改多行(即使查询表达式命中多行,默认也只改一行,如果想修改多行,可以用此选项)
删除数据:
删除记录:db.表.remove({条件})
示例:db.product.remove({name:'xiaomi'})
只删除一行:db.表.remove({条件},{justOne:true/false}) 默认为false
删除字段:db.表.update({条件},{'$unset':{字段1:1/0,字段2:1/0,.....}}) (删除字段的值不管是1或是0,都会删除字段)
删除文档(表):db.表.drop()
///
mongodb程序(bin目录)功能解释:
核心:
mongod:数据库核心进程
mongos:查询路由器,集群(分片)时用
mongo:交互终端(客户端)
数据导出导入:
mongoexport:导出json,csv,tsv格式
mongoimport:导入json,csv,tsv格式
二进制导出导入:
mongodump:导出bson数据
mongorestore:导入bson
bsondump:bson转换为json
mongolog:
诊断工具:
mongostat:
mongotop
mongosniff:用来检查mongo运行状态
//
游标:
游标:通俗的讲,游标不是查询结果,而是查询的返回资源或者接口,通过这个接口,你可以逐条读取。就像php中的fopen打开文件,得到一个资源一样,可以一行一行的读文件。
声明游标:
var cursor = db.product.find({条件});
cursor.hasNext() 判断游标是否已经取到尽头
cursor.Next() 取出游标的下一个单元
例子:
var cursor = db.product.find({price:{$gt:1000}});
(1)
while(cursor.hasNext()){
printjson(cursor.Next())
}
(2)
for(var doc=trur;cursor.hasNext();){
printjson(cursor.Next())
}
(3)
cursor.forEach(回调函数)
cursor.forEach(function(obj){
printjson(obj)
})
通过cursor一次性得到所有的数据,并返回数组
例子:
var cursor = db.product.find({price:{$gt:1000}});
printjson(cursor.toArray()); //得到所有行
printjson(cursor.toArray()[2]); //得到第二行
游标在分页中使用:
例子:
db.product.find().limit(10).skip(0)
db.product.find().limit(10).skip(10)
db.product.find().limit(10).skip(20)
/
索引:
查看执行计划:db.product.find({price:1000}).explain();
索引创建:
1、索引能提高查询效率,但是降低了写入速度,权衡常用的查询字段,不必在太多列上建立索引
2、在mongodb中,索引可以按字段升序、降序来创建,便于排序
3、默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引
常用命令:(1:升序创建索引 -1:降序创建索引)
查看当前索引状态:db.collection.getIndexes();
创建普通的单列索引:db.collection.ensureIndex({field:1/-1});
创建多列索引:db.collection.ensureIndex({field1:1/-1,field2:1/-1})
创建子文档索引:db.collection.ensureIndex({field.subfield:1/-1});
创建唯一索引:db.collection.ensureIndex({field.subfield:1/-1},{unique:true});
创建稀疏索引:
稀疏索引的特点------如果针对field做索引,针对不含field列的文档,将不建立索引。
与之相对,普通索引会把该文档的field列的值认为NULL,并建立索引。
适用于:小部分文档含有某列时
db.collection.ensureIndex({field:1/-1},{spare:true});
创建哈希索引:
哈希索引速度比普通索引块,但是,无法对范围查询进行优化。
适用于:随机性强的散列
db.collection.ensureIndex({field:'hashed'});
删除索引:
删除单个索引:db.collection.dropIndex({field:1/-1});
删除所有索引:db.collection.dropIndexes();
重建索引:
一个表在经过很多次修改后,导致表的文件产生的空洞,索引文件也会频繁更新。
可以通过索引的重建,减少索引文件碎片,并提高索引的效率,类似mysql中的optinize table 表名
语法:db.collection.relIndex()
作用:重建collection中的所有索引,包括_id.减少索引文件碎片
//
mongo数据导出导入:
数据导出:
mongoexport -h host -p port -u username -p password
-d database 要导出的数据库
-c collection 要导出的集合(表)
-f 要导出的列
-q 查询的条件(用引号包起来)
-o 导出的文件名
--csv 导出csv格式(便于和传统数据库交换数据)
示例:
./bin/mongoexport -d test -c product -f name,price -o test.dat -q '{price:{$gte:1000}}'
./bin/mongoexport -d test -c product -f name,price -o test.csv -q '{price:{$gte:1000}}' --csv
数据导入:
mongoimport -h host -p port -u username -p password
-d 待导入的数据库
-c collection 要导入的集合(表),不存在会自动创建
-f 要导入的列
--type 要导入的数据类型 csv/json(默认)
--file 备份文件的路径
--headline 去掉备份文件中第一行数据内容
示例:
示例一:导入json类型
./bin/mongoimport -d test -c product --file E:/mongodb/backData/product.json
示例一:导入csv类型
./bin/mongoimport -d test -c product --type csv -f name,price --file E:/mongodb/backData/product.csv
./bin/mongoimport -d test -c product --type csv --headline -f name,price --file E:/mongodb/backData/product.csv
二进制导入导出:
mongodump 导出二进制bson结构及其索引信息
mongodump -h host -p port -u username -p password
-d 数据库名
-c 表名
-f 要导出的列
-o, --out:代表导出的文件输出目录;
-q, --query:代表查询条件;
-j,--numParallelCollections =要并行转储的集合数(默认为4)
--gzip,使用Gzip压缩存档;
--oplog,使用oplog进行时间点快照;
--authenticationDatabase,指定用户鉴定库
示例:
1、mongodump -d test [-c product] 默认是导出到mongo下的dump目录下
2、mongodump -u root -p root --authenticationDatabase admin -d test -c goods -o ../backData/
规律:
1、导出的文件放在以数据库命名的目录下
2、每个表导出2个文件,分别是bson结构的数据文件,json的索引信息
3、如果不声明表名,将导出所有表
mongorestore 导入二进制文件
-h,--host :代表远程连接的数据库地址,默认连接本地Mongo数据库;
--port:代表远程连接的数据库的端口,默认连接的远程端口27017;
-u,--username:代表连接远程数据库的账号,如果设置数据库的认证,需要指定用户账号;
-p,--password:代表连接数据库的账号对应的密码;
--authenticationDatabase,指定用户鉴定库
-d,--db:代表连接的数据库;
-c,--collection:代表连接数据库中的集合;
--dir = <目录名称>输入目录
--drop导入前删除数据库中集合;
--gzip,解压Gzip压缩存档还原;
--oplog,重放oplog以基于时间点还原;
--oplogFile = <文件名>指定重播oplog的oplog文件
示例:
./bin/mongorestore -d test --directoryperdb dump/product/ (mongodump时的备份目录)
mongorestore -u root -p root --authenticationDatabase admin -d test -c goods -o ../backData/数据库名称
备注:二进制备份,不仅可以备份数据,还可以备份索引,备份的数据比较小。
///
replication set 复制集
replication set 多台服务器维护相同的数据副本,提高服务器的可用性
replication set 设置全过程:
1、创建目录
mkdir -p /data/r0 data/r1 data/r2
2、启动3个实例,且声明实例属于某个复制集
./bin/mongod --port 27017 --dbpath /data/r0 --smallfiles --replSet rsa --fork --logpath /data/log/mongo17.log
./bin/mongod --port 27018 --dbpath /data/r1 --smallfiles --replSet rsa --fork --logpath /data/log/mongo18.log
./bin/mongod --port 27019 --dbpath /data/r2 --smallfiles --replSet rsa --fork --logpath /data/log/mongo19.log
3、连接27017mongo服务后,在admin库下配置
rsconf = {
_id:'rsa',
members:[
{_id:0,host:'192.168.1.201:27017'},
{_id:1,host:'192.168.1.201:27018'}
{_id:2,host:'192.168.1.201:27019'}
]
}
4、根据配置做初始化
rs.initiate(rsconf)
5、添加节点
rs.add('192.168.1.201:27018');
rs.add('192.168.1.201:27019');
6、查看状态
rs.status()
7、删除节点
rs.remove('192.168.1.201:27019');
8、主节点插入数据
use test;
db.product.insert({'name':'huawei11','price':1000})
9、连接secondary查询同步情况
Sat Aug 17 16:03:55.786 javaScript execution failed:error {'$err':'not master and slaveOK=false','code':13425}
出现以上错误,是因为slave默认不许读写。用rs.slaveOK()解决
///
shard分片:
1、启动2个实例
./bin/mongod --port 27017 --dbpath /data/m17/ --smallfiles --fork --logpath /data/log/mongo17.log
./bin/mongod --port 27018 --dbpath /data/m18/ --smallfiles --fork --logpath /data/log/mongo18.log
2、启动一个configsvr实例
./bin/mongod --port 27020 --dbpath /data/m20/ --smallfiles --fork --logpath /data/log/mongo20.log --configsvr
3、启动一个mongos实例
./bin/mongos --port 30000 --smallfiles --fork --logpath /data/log/mongo30.log --configdb 192.168.1.202:27020
4、登录到mongos实例服务器,增加片节点
sh.addShard('192.168.1.202:27017')
sh.addShard('192.168.1.202:27018')
5、设置分片规则
sh.enableSharding(dbName); //添加待分片的库
sh.shardCollection('dbName.collectionName',{field:1}) //添加待分片的表
Field是collection的一个字段,系统将会利用field的值来计算应该分到哪一个片上,这个field就好片键(shardKey),一般用主键
示例:
sh.enableSharding('test') //设置test库可以进行分片
sh.shardCollection('test.product',{id_num:1}) //设置test库下product表按id_num字段来分片
注意:mongodb不是从单篇文档的级别来绝对平均的散落在各个片上,而是在N片文档上形成一个块(chunk),他是优先放在某个片上,当这个片上的chunk比另一个片上的chunk区别比较大时,(>=3)就会把本片上的chunk移到另一个片上,以chunk为单位,维护片之间的数据均衡。
问:为什么插入10万条数据,才在一个片中分了两个块?
说明一个chunk比较大(默认64M)。可以在config数据库中修改chunksize的值
问:既然优先在某个片上插入,当chunk失衡时,在移动chunk会随着数据的增多,shard的实例之间有chunk来回移动的现象,这将带来什么问题?
服务器之间的IO的增加。可以自定义一个规则,某N条数据形成一个块,预告分配M个chunk,并将M个chunk预告分配在不同片上。以后的数据直接各自在预分配好chunk上。避免服务之间IO的增加。可以进行手动预先分片
示例:手动预先分40个片,每个片存储1000条数据(大致存储数据会平均分配),预先在1K,2K,3K,...40K这样的界限切好chunk(刚开始预先分片chunk上的数据是空的),这些chunk将会均匀移动到各片上。数据添加到预先分配好的chunk上,chunk就不会来回移动,减少服务器上的频繁IO操作
for(var i=1;i<=40;i++){
sh.splitAt('test.product',{id_num:i*1000})
}
5、查看增加片的状态
sh.status()
//
replication set 复制集和shard分片相结合
假如有192.168.1.202、192.168.1.203、192.168.1.204三台服务器
其中 192.168.1.202 服务器为configsvr
1、
(1) 192.168.1.203 创建复制集
./bin/mongod --port 27017 --dbpath /data/r0 --smallfiles --replSet rs3 --fork --logpath /data/log/mongo17.log
./bin/mongod --port 27018 --dbpath /data/r1 --smallfiles --replSet rs3 --fork --logpath /data/log/mongo18.log
./bin/mongod --port 27019 --dbpath /data/r2 --smallfiles --replSet rs3 --fork --logpath /data/log/mongo19.log
(2) 配置
rsconf = {
_id:'rs3',
members:[
{_id:0,host:'192.168.1.203:27017'},
{_id:1,host:'192.168.1.203:27018'}
{_id:2,host:'192.168.1.203:27019'}
]
}
(3) 根据配置做初始化
rs.initiate(rsconf)
2、
(1) 192.168.1.204 创建复制集
./bin/mongod --port 27017 --dbpath /data/r0 --smallfiles --replSet rs4 --fork --logpath /data/log/mongo17.log
./bin/mongod --port 27018 --dbpath /data/r1 --smallfiles --replSet rs4 --fork --logpath /data/log/mongo18.log
./bin/mongod --port 27019 --dbpath /data/r2 --smallfiles --replSet rs4 --fork --logpath /data/log/mongo19.log
(2) 配置
rsconf = {
_id:'rs4',
members:[
{_id:0,host:'192.168.1.204:27017'},
{_id:1,host:'192.168.1.204:27018'}
{_id:2,host:'192.168.1.204:27019'}
]
}
(3) 根据配置做初始化
rs.initiate(rsconf)
3、192.168.1.202服务器上
./bin/mongod --port 27020 --dbpath /data/m20/ --smallfiles --fork --logpath /data/log/mongo20.log --configsvr
4、192.168.1.202服务器上启动一个mongos实例
./bin/mongos --port 30000 --smallfiles --fork --logpath /data/log/mongo30.log --configdb 192.168.1.202:27020
5、登录到mongos实例服务器,增加片节点
sh.addShard('rs3/192.168.1.203:27017')
sh.addShard('rs4/192.168.1.204:27017')
6、设置某个库的分片规则
sh.enableSharding('test') //设置test库可以进行分片
sh.shardCollection('test.product',{id_num:1}) //设置test库下product表按id_num字段来分片
7、手动预先分片
for(var i=1;i<=40;i++){
sh.splitAt('test.product',{id_num:i*1000})
}
8、在mongos实例服务器上就可以创建数据库,表。插入数据测试