一、MongoDB概念介绍
1、NoSQL简介
- 简单的扩展
- 快速的读写
- 低廉的成本
- 灵活的数据模型
不足:
- 不提供对SQL的支持
- 支持的特性不够丰富
- 现有的产品不够成熟
- 大大提高对海量数据的访问效率。根据官方提供的性能测试表明,每秒可以处理0.5W-1.5W次读写请求,当数据达到50GB以上,MongoDB的访问速度是MySQL的10倍以上
- 面向集合存储,易存储对象类型的数据
- 模式自由。存储在数据库的文件,不需要知道它的任何结构定义
- 支持动态查询。
- 支持完全索引
- 支持复制和故障恢复
- 使用高效的二进制数据存储
- 文件存储格式为BSON
- 支持Java、Ruby、Python、PHP等多种语言
5、与关系型数据库的比较
6、下载、安装
下载通过官网:https://www.mongodb.com/download-center#community
curl -0 https://fastdl.mongodb.org/osx/mongodb-osx-ssl-x86_64-3.2.6.tgz
安装
- 新建存放数据库路径:假设在当前user目录下新建/data/db
- 在刚下载的mongodb解压缩包目录中,切换到/mongodb-osx-x86_64-3.2.6/bin目录下,执行命令:mongod --dbpath /data/db
或 - 配置环境变量 echo "export PATH=mongodb解压后存放路径/bin:$PATH">>~/.bash_profile,直接在终端输入 mongod --dbpath /data/db即可启动服务端
- 客户端启动:打开终端,如果配置了环境变量,直接mongo host:port,如果没有配置环境变量:目录切换到/bin目录下,.mongo host:port
比较快捷的方式:创建一个.sh或.bat脚本进行启动
二、MongoDB常用操作
1、基本操作
- 创建数据库: use dbName
use 命令后跟的数据库名,如果存在就进入此数据库,如果不存在就创建,所以这种创建方式又叫隐式创建
注意:使用命令use mydb1创建数据库后,并没有真正生成对应的数据文件,如果此时退出,此数据库将被删除,只有在此数据库中创建集合后,才会真正生成数据文件
- 删除当前数据库:db.dropDatabase()
- 查看所有数据库:show dbs
- 查看当前所在数据库:db
- 查看当前库所有的集合:show collections 或 show tables
- 集合的创建有两种:显式创建和隐式创建
显式创建:db.createCollection("集合名称");
隐式创建:db.集合名称.insert({key:"value"}); 创建集合并向集合中添加数据 - 删除集合:db.集合名称.drop()
- 删除数据库:db.dropDatabase();
- 向集合添加文档:db.集合名称.insert();
也可以通过for循环批量插入多个文档
for(var i=0; i<100; i++) {
db.users.insert({});
}
也可以通过db.集合名称.save()插入文档,save与insert的不同之处在于:使用insert插入文档时,如果_id已经存在,则不能插入,类似关系型数据库中的主键id;如果使用save插入文档,如果_id存在,就执行修改,否则新增 - 删除集合中的文档:db.集合名称.remove({}); 注意:不加删除条件,删除集合中的所有数据,但不会删除集合本身和索引,在3.x版本后,不能删除全部;如果加了删除条件,则删除改条件的文档
2、集合查询
下面的查询和修改默认集合名称:users
- 查询集合中文档个数:db.users.count()
- 查询集合中的文档:db.users.find({}) 返回全部;db.users.findOne({}) 返回一条
- 查询集合中的文档,返回特定的键
db.users.find({},{age:0}) 第一个{}代表查询条件,改集合会返回除了age字段外的所有字段
db.users.find({},{name:1}) 会返回只有name的字段 - 查询条件
条件表达式(<, <=, >, >=, !=)
db.users.find({age:{$gt:10}}) 查询年龄大于10
db.users.find({age:{$gte:10}}); 年龄大于等于10
db.users.find({age:{$lt:10}}); 年龄小于10
db.users.find({age:{$lte:10}}); 年龄小于等于10
db.users.find({age:{$ne:10}}) 年龄不等于10
关系型数据库中的between and查询
db.users.find({age:{$gt:10,$lt:20}}) - $or 相当于关系型数据库的or db.users.find({$or:[{}]})
db.users.find({$or:[{name:"zhangsan"},{age:{$gt:20}}]}) 查询name="zhangsan" or age > 20 - 如果是关系型数据库中的and
db.users.find({name:"zhangsan",age:30}); - $nor 过滤掉某些数据库 db.users.find({$nor:[{}]});
db.users.find({$nor:[{name:"zhangsan"}]}) - $in 类型关系型数据库的in
db.users.find({age:{$in:[10,20,30]}}) - $nin 与$in相反
- $exists查询某个键是否存在的记录
db.users.find({name:{$exists:1}}) 查询包含name字段的文档
db.users.find({name:{$exists:0}}) 查询不包含name字段的文档
3、排序
- 根据字段排序 db.users.find().sort({field:1}) 1:生序 -1:降序
4、分页
- db.users.find().skip(0).limit(3) 从第0条开始,显示3条
-
db.users.find().sort({id:-1}).skip(0).limit(3)
5、统计
- db.users.count()
- db.users.find({}).count()
6、游标
- 将结果集存在一个变量中
var userInfo = db.users.find();
while(userInfo.hasNext()){
userInfo.next()
}
7、更新
语法:db.collection.update(criteria,objNew,upsert,multi)
参数说明:
criteria:用于设置查询条件的对象
objNew:用于设置更新内容的对象
upsert:如果记录已经存在,更新它,否则新增一个记录,取值为0或1
multi:如果有多个符合条件的记录,是否全部更新,取值为0或1
注意:默认情况下,只会更新第一个符合条件的记录
一般情况下后两个参数分别为0,1 ,即:
db.collection.update(criteria,objNew,0,1)
- 不好的更新方法
如果更新这样写:$.users.update({name:"zhangsan"},{age:50})这种修改有两个问题,就是会使用新文档覆盖原来的文档,如果原来文档有多个键,修改后就有可能被覆盖只剩下一个键了
第二个问题为即使符合更新条件的文档有多个也只会更新第一个符合条件的记录
-
$set 更新集合中的文档, $set 用来指定一个键的值,如果这个键不存在,则创建它。例如:
给name为zhangsan的文档添加address,可以使用命令:db.c1.update({name:”zhangsan”},{$set:{address:”bj”}})
-
$inc 将集合中name为user1的age加1,其它键不变, $inc表示使某个键值加减指定的数值$.users.update({name:"zhangsan"},{$inc:{age:10}})
- $unset 删除指定的key
db.users.update({name:"zhangsan"},{$unset:{age:1}})
8、索引
目的:。。。
- 创建普通索引
db.users.ensureIndex({field:1}); 1:正序索引 -1:降序索引 - 索引起名字
db.users.ensusreIndex({field:1},{name:"my_index"}) - 查看查询索引使用情况
db.users.find({key:value}).explain()
explain会返回查询使用的索引情况,耗时和扫描文档数的统计信息。
"cursor":"BasicCursor"表示没有使用索引。
"nscanned":1 表示查询了多少个文档。
"n":1 表示返回的文档数量。
"millis":0 表示整个查询的耗时。 - 唯一索引
db.users.ensureIndex({field:1},{unique:true});
9、固定集合
固定集合指的是事先创建而且大小固定的集合
固定集合特性:固定集合很像环形队列,如果空间不足,最早的文档就会被删除,为新的文档腾出空间。一般来说,固定集合适用于任何想要自动淘汰过期属性的场景,没有太多的操作限制。
创建固定集合使用命令:db.createCollection(“collectionName”,{capped:true,size:100000,max:100});
size指定集合大小,单位为KB,max指定文档的数量
当指定文档数量上限时,必须同时指定大小。淘汰机制只有在容量还没有满时才会依据文档数量来工作。要是容量满了,淘汰机制会依据容量来工作。
10、导出
mongoexport -d 数据库名称 -c 集合 -o 输出路径
- -d 指明使用的库
- -c 指明要导出的表
- -o 指明要导出的文件名
- -csv 制定导出的csv格式
- -q 过滤导出
- --type <json|csv|tsv>
- 导出其它主机加配置:mongoexport --host ip --port xxx
导入
mongoimport --db 数据库名称 --collection 集合 --file 文件
11、备份
mongodump --host 127.0.0.1:27017 -d 数据库 -o 备份路径
还原
mongorestore --host 127.0.0.1:27017 -d 数据库 --dir 文件路径
12、安全和认证
每个MongoDB实例中的数据库都可以有许多用户。如果开启了安全性检查,则只有数据库认证用户才能执行读或者写操作。
mongodb默认不启用授权认证,只要能连接到该服务器,就可连接到mongod。若要启用安全认证,需要更改配置文件参数auth
- 创建某个数据库的管理用户 注:数据库还以users为例
use users
添加用户
db.addUser("tom","123456"); // 默认拥有改数据库的所有权限
db.addUser("tom","123456",true); // 拥有改数据库的只读权限 第三个参数:readOnly默认false
查看所有的用户
db.system.users.find();
删除用户
db.removeUser("tom");
- 创建超级用户
在admin数据库创建的用户都是超级用户,可以操作任何数据库
二、V2.4对用户权限管理做了全新的调整,把权限细化了,增强了安全性
权限管理分为:数据库的操作权限、数据库用户的管理权限、集群的管理权限
mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名、密码和数据库信息。
use admin创建用户
db.createUser({user:"mongo1",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
上面创建的用户mongo1拥有对所有数据管理用户的权限,创建好用户后,可以重新设置打开服务端
mongod --dbpath /data/db --auth
打开客户端终端
mongo
use myTest
如果执行show collections或db.p.insert({name:"123"}) 会怎样呢?
用拥有userAdminAnyDatabase权限的用户来创建普通用户,要先登陆才能创建
先登陆:use admin db.auth("mongo1","123456")
再创建:use myTest
db.createUser({user:"common1",pwd:123456",roles:[{role:"userAdminAnyDatabase",db:"myTest"}]})
就可以正常操作了
常用的角色:read、readWrite 指定数据库的只读(读写)权限,主要是针对库的集合操作
dbAdmin:指定数据库的管理权限
userAdmin:指定数据库的用户管理权限
readAnyDatabase 任何数据库的只读权限(和read相似)
readWriteAnyDatabase 任何数据库的读写权限(和readWrite相似)
userAdminAnyDatabase 任何数据库用户的管理权限(和userAdmin相似)
dbAdminAnyDatabase 任何数据库的管理权限(dbAdmin相似)
13、主从复制
主从复制是MongoDB最常用的复制方式。这种方式非常灵活,可用于备份、故障恢复、读扩展等。
最基本的设置方式就是建立一个主节点和一个或者多个从节点,每个从节点要知道主节点的地址。运行mongod --master就启动了主服务器。运行mongod --slave --source master_address 则启动了从服务器,其中master_address就是上面主节点的地址。
主服务器:mongod --dbpath /data/db --master --port 12345
从服务器:mongod --dbpath /data/slave --slave --source ip:12345 --port 23456
在从服务器查询会有问题
http://wengzhijuan12.blog.163.com/blog/static/3622414520137104257376/
其它配置项:
--only 从节点指定复制某个数据库,默认是复制全部数据库
--slavedelay 从节点设置主数据库同步数据的延迟(单位是秒)
--fastsync 从节点以主数据库的节点快照为节点启动从数据库
--autoresync 从节点如果不同步则从新同步数据库
--oplogSize 主节点设置oplog的大小(主节点操作记录存储到local的oplog中)
14、副本集
副本集就是有自动故障恢复功能的主从集群。
主从集群和副本集最大的区别就是副本集没有固定的“主节点”;整个集群会选出一个“主节点”,当其挂掉后,又在剩下的从节点中选中其他节点为“主节点”,副本集总有一个活跃点(primary)和一个或多个备份节点(secondary)。
"replSetInitiate":{
"_id":“child",
"members":[
{
"_id":1,
"host":"localhost:10001",
"priority":3
},
{
"_id":2,
"host":"localhost:10002",
"priority":2
},
{
"_id":3,
"host":"localhost:10003",
"priority":1
}
]}});
--replSet 指定副本集 后面紧跟着副本集的名称
--logappend 日志文件末尾添加
--port 指定端口号
db.runCommand({}) 初始化副本集
初始化文档:
"_id":“itcast", 指副本集的名称
"members":[...] 副本集的服务器列表 每个列表有个
"_id": 每个服务器的唯一id,
"host" 指定服务器的主机,
"priority"设置优先级,默认优先级为1,可以是1-1000的数字