摘要:MongoDB 基础,2016-10-23初次编辑,2018-11更新
介绍
数据库:
1.有组织的存放数据
2.可以按照不同的需求进行查询
分类:
1.Sql数据库:Oracle、Mysql…
2.Nosql数据库:Redis、MongoDB
Sql与NoSql的区别:Sql具有实时一致性,支持事务,可多表联查,限制较多,对表的应用不够灵活,(在没有特别多的事务需求情况下)额外的特性比较消耗性能;NoSQL操作简单,方便扩展,拥有更好的性能
MongoDB的特点:
- 无数据结构限制
- 没有表结构的概念,每条记录可以有完全不同的结构
- 业务开发方便快捷
- Sql数据库需要事先定义表结构再使用
- 完全的索引支持
- redis的key-value
- hbase的单索引,二级索引需要自己实现
- 单键索引,多键索引:{x:1,y:1}
- 数组索引:[“hello”,”world”]
- 全文索引:”hello world”(中文)
- 地理位置索引:2D
- 方便的冗余与扩展
- 复制集保证数据安全
- 分片扩展数据规模
- 良好的支持
- 完善的文档
- 齐全的驱动支持
window环境
安装
首先要下载适合自己电脑的版本,地址:http://www.mongodb.org/downloads,然后安装到D:\mongodb目录下。之后主动创建文件夹D:\mongodb\data,再在data目录下创建db和log两个文件夹,在log目录下创建mongodb.log文件
结构:
D:\mongodb:
- GNU-AGPL-3.0
- README
- THIRD-PARTY-NOTICES
- bin
- data
- db
- log
- mongodb.log
启动MongoDB
dos命令界面cd进入D:\mongodb\bin目录下(可以将D:\mongodb\bin添加到环境变量里更方便),执行命令启动MongoDB服务器
1 | D:\mongodb\bin>mongod.exe --logpath=D:\mongodb\data\log\mongodb.log --dbpath=D:\mongodb\data\db |
–logpath:日志路径
–dbpath:数据库路径
连接MongoDB
当mongod.exe被关闭时,mongo.exe无法连接到数据库。只能再新打开一个dos命令界面cd进入D:\mongodb\bin目录下,输入mongo或mongo.exe连接MongoDB数据库进入MongoDB Shell交互环境,可以对MongoDB进行操作和管理。数据库默认text文档,默认监听的端口是27017。
1 | D:\mongodb\bin>mongo |
Ctrl
+C
退出
将MongoDB服务器作为Windos服务运行
每次连接数据库都要重新执行mongod.exe比较麻烦,可以将MongoDB安装为windows服务。进入D:\mongodb\bin目录下执行命令
1 | D:\mongodb\bin>mongod.exe –logpath “D:\mongodb\data\log\mongodb.log” –logappend –dbpath “D:\mongodb\data\db” –serviceName “MongoDB” –install |
–logappen:使用追加的方式写日志
–serviceName:服务名称
–install:作为一个Windows服务安装.
如果要删除该服务执行命令
1 | D:\mongodb\bin>mongod.exe –logpath “D:\mongodb\data\log\mongodb.log” –dbpath “D:\mongodb\data\db” –serviceName “MongoDB” –remove |
–remove:删除服务
安装成功后可以执行命令启动
1 | net start MongoDB |
关闭MongoDB服务
1 | net stop MongoDB |
mongodb.conf
在命令行下运行MongoDB服务器和连接服务器修改属性很不方便,添加一个配置文件mongodb.conf来配置所有属性比较方便,比如修改端口为12345内容如下
1 | port = 12345 |
启动服务器
1 | D:\mongodb\bin>mongod.exe -f ../mongod.conf |
新打开一个命令窗口,连接服务器
1 | D:\mongodb\bin>mongo 127.0.0.1:12345/text |
详细配置看这篇文章mongodb.conf配置文件详解
如果要作为windows服务运行,修改mongod.conf的配置
1 | dbpath = D:\mongodb\data\db |
打开命令行
1 | D:\mongodb\bin>mongod.exe -f ../mongod.conf –install |
删除则是将install
改为remove
注意:
1.数据库的所有操作记录都可以在日志mongodb.log中查看
2.出现10061 由于计算机积极拒绝的错误,可能是路径不对,也可能是mongodb异常关闭造成的。删除db目录下的mongod.lock文件,检查路径是否正确。mongod.lock文件是mongo服务端启动后在硬盘中创建的一个锁文件,这个文件还会记录mongod在运行过程中的一些状态,以便在正常重新启动服务时能够获取异常信息提示。如果你正常退出mongod服务,该文件即使还存在,也不会影响下一次启动mongod服务
3.出现mongodb.exe不是有效的程序,复制压缩包内的mongodb.exe替换掉即可
mac环境
安装配置
1、下载
1 | brew install mongodb |
2、创建数据目录
mongodb默认数据文件是放到根目录下的data/db中,创建该目录
1 | sudo mkdir -p /data/db |
-p:如果没有可以接连创建目录
3、修改权限
赋予当前用户对/data/db的读写权限
1 | sudo chown `id -u` /data/db |
-R:表示连同子目录一起授权
id -u:获取当前用户的id
4、修改.bash_profile文件,将其添加到环境变量,如果没有要先创建
1 | touch ~/.bash_profile |
按i
进入输入模式,在最后一行加入(安装路径要写自己的,brew安装的注意版本)
1 | export PATH=/usr/local/Cellar/mongodb/4.0.2/bin:$PATH |
然后按esc
退出输入模式,再输入:wq
保存修改
查看.bash_profile中的环境变量以确认添加成功
1 | cat ~/.bash_profile |
5、立刻生效,bash会在每次启动时加载.bash_profile,修改后需要执行一次该文件添加的变量才可以生效,重启或者执行命令
1 | source .bash_profile |
6、修改mongodb的配置
mongodb的配置文件是/usr/local/etc/mongod.conf
,本地练习一定要保证bindIp为127.0.0.1
1 | storage: |
7、启动、连接mogodb
启动,提示27017端口等待连接说明启动成功
1 | mongod |
不要关闭这个shell窗口,再开启一个新的shell连接mongodb
1 | mongo |
最后一句出现>
等待输入命令说明连接成功,同时第一个shell窗口也会更新连接信息
1 | To permanently disable this reminder, run the following command: db.disableFreeMonitoring() |
Ctrl
+C
结束连接
8、停止服务Ctrl
+C
或者使用命令
1 | use admin; |
如果不停止服务,再次启动服务会报错。如果报错可以查看有哪些与mongodb相关的进程
1 | ps -ef | grep mongo |
或者查看27017端口占用情况获得mongodb的信息
1 | lsof -i tcp:27017 |
查到mongod的进程pid杀死
1 | kill 36970 |
概念
在mongodb中基本的概念是数据库、集合、文档
数据库
一个mongodb中可以建立多个数据库。MongoDB的默认数据库为”db”,该数据库存储在data目录中。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
数据库名可以是满足以下条件的任意UTF-8字符串
- 不能是空字符串
- 不得含有’ ‘(空格)、.、$、/、\和\0 (空宇符)
- 应全部小写
- 最多64字节
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库
- admin: 从权限的角度来看,这是”root”数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器
- local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息
集合
集合就是 MongoDB 文档组,类似于RDBMS(关系数据库管理系统:Relational Database Management System)中的表格。集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
合法的集合名:
- 集合名不能是空字符串” “
- 合名不能含有\0字符(空字符),这个字符表示集合名的结尾
- 集合名不能以”system.”开头,这是为系统集合保留的前缀
- 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$
文档
文档是一个键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
需要注意的是:
- 文档中的键/值对是有序的
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)
- MongoDB区分类型和大小写
- MongoDB的文档不能有重复的键
- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符
文档键命名规范:
- 键不能含有\0 (空字符)。这个字符用来表示键的结尾
- 和$有特别的意义,只有在特定环境下才能使用
- 以下划线”_”开头的键是保留的(不是严格要求的)
数据库、集合(表)操作
1 | show dbs #查看所有数据库 |
插入文档
MongoDB使用insert()方法向集合中插入文档,文档的数据结构和JSON基本一样,而且支持js语法
1 | > db.collection.insert({name:"xiaowang",age:24}) |
查询文档
find()方法以非结构化的方式来显示所有文档,参数是查询条件,无参数时返回全部文档
pretty()方法以格式化的方式来显示所有文档
1 | > db.collection.find() |
其中”_id”是MongoDB自动添加的全局唯一标识,可以自己设定但值不能重复
count()方法来记录返回多少条数据
1 | > db.number.find().count() |
skip()方法来跳过指定数量的数据
limit()方法指定从MongoDB中读取的文档数量
1 | > db.number.find().skip(2).limit(1) |
查找跳过2个文档后的一条数据
更新文档
update()方法用于更新已存在的文档,默认更新符合条件的第一条数据。至少有两个参数,第一个参数query是查询条件,第二个参数update是更新的对象和一些操作符
1 | > db.number.update({x:0},{x:999}) |
将x的值0更新为999
$set操作符用来指定一个键并更新键值,若键不存在则创建新键值对
1 | > db.number.update({x:1},{y:1}) |
查找{x:1}未找到,因为已将{x:1}更新为{y:1}。使用$set后,先查找是否有该键值对,有就更新,无则不发生更新
第三个参数upsert:可选,如果未找到要更新的文档,值为true时创建新的文档插入,默认是false,不插入
1 | > db.number.update({x:3},{x:1003},true) |
如果{x:3}存在则更新为{x:1003},如果不存在则创建一条{x:1003}的数据
第四个参数multi:可选,默认为false只更新符合条件的第一条数据,如果为true,则所有符合的文档全部修改
1 | > db.number.update({x:4},{$set:{y:4}},false,true) |
将集合中已有的符合{x:4}的文档中y字段全部添加或更新为{y:4}
删除文档
remove()方法必须含有一个参数用来指定删除文档的条件
1 | db.number.remove({x:5}) |
删除{x:5}的文档
索引
数据量大时,创建索引要消耗一定的时间,所以在建表时就将索引创建完毕,否则会对数据库性能造成较大影响。使用索引可以极大地提高查询效率,但同时会增加磁盘空间的消耗,降低写入性能
索引分类:_id索引、单键索引、多键索引、复合索引、过期索引、全文索引(文本索引)、地理位置索引
getIndexes方法用来查看索引情况
1 | > db.number.getIndexes() |
参数解释
v:索引的版本号,默认的索引版本取决于mongod创建索引时运行的版本
key:索引所在的字段和排列方式,1为正向(升序),-1为逆向(降序)
name:索引的名字
ns:索引所在的集合位置
_ID索引
_id索引是大多数集合默认建立的索引,每个插入的文档都会自动生成唯一的_id字段,值可以修改但不能重复
单键索引
单键索引是最普通的索引,不会自动创建,如果索引已经存在则直接返回成功。单键索引建立索引的键值为单一的值:字符串、数字、日期等
1 | > db.number.ensureIndex({x:1}) |
在字段x键上创建索引,1表示正向排列。索引默认的name是字段名+下划线+排序方式
多键索引
多键索引与单键索引类似,但其建立索引字段的键值为数组
1 | > db.number.insert({z:[1,2,3]}) |
复合索引
当查询条件不止有一个,需要多个字段,多个单键索引联合,就使用复合索引
1 | > db.number.ensureIndex({x:1,y:-1}) |
按x正向,y逆向创建复合索引
过期索引
过期索引是指过一段时间后会过期消失的索引。索引过期后,相对应的文档数据也会被删除。适合存储一段时间后消失的数据,如:用户登录、日志。
1 | > db.number.insert({time:new Date()}) |
在字段time键上建立正向排列60秒后过期的过期索引,expireAfterSeconds指定过期的时间单位是秒
注意:
1.过期索引对应键的键值必须为指定的时间类型,是ISODate(世界标准时间)或者ISODate数组,不能使用时间戳,否则不能自动删除
2.过期索引不能是复合索引
3.如果指定了ISODate数组,则按最小的时间进行删除
4.删除时间是不精确的,最小间隔是60秒。即使是设置expireAfterSeconds的值小于60,也是60秒后删除,而且执行删除也需要时间
全文索引
可以为一个字段创建全文索引,字段名:"text"
1 | > db.number.ensureIndex({key:"text"}) |
多个字段,多个字段名:"text"
键值对
1 | > db.number.ensureIndex({key1:"text",key2:"text"}) |
所有字段,固定键值对"$**":"text"
1 | > db.number.ensureIndex({"$**":"text"}) |
查找包含文本aa的文档
1 | > db.number.find({$text:{$search:"aa"}}) |
查找包含文本aa或bb或cc的文档
1 | > db.number.find({$text:{$search:"aa bb cc"}}) |
查找包含文本aa或bb但没有cc的文档,符号-
表示不包含
1 | > db.number.find({$text:{$search:"aa bb -cc"}}) |
查找同时包含文本aa、bb和cc三者的文档,使用双引号""
包裹文本,为防止双引号组合混乱要使用\
转译
1 | > db.number.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}}) |
相似度
将相似度的高的文档排在最前面,可以快速、准确地找到所需的文档
1 | > db.number.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}}) |
注意:
1.每次查询只能指定一个文本查询
2.文本查询不能出现在$nor中
3.有文本查询时,hint将失效
4.不支持中文
地理位置索引
将一些点的位置存储在MongoDB中,创建后可以按照位置查找其他点
分类:
1、2d索引,用于查找平面上的点
2、2dsphere索引,用于查找球面上的点
用途:
1、查找距离某个点一定间隔内的点
2、查找包含在某个范围内的点
2D索引
2d索引是平面地理位置索引
创建索引方式
1 | > db.number.ensureIndex({sp:"2d"}) |
位置表示方式:[经度,纬度],经度范围:[-180,180],纬度范围:[-90,90]
文档插入格式
1 | > db.number.insert({sp:[180,90]}) |
查询方式:
1.使用$near查找附近的点
1 | > db.number.find({sp:{$near:[11,22],$maxDistance:10}}) |
$maxDistance规定了最大距离不超过10,单位同文档坐标系统的单位一致,2d索引不支持$minDistance属性
2.使用$geoWithin查询某个形状内的点,有3种形状
a.$box矩形,由两个点的横纵坐标交叉围成
1 | > db.number.find({sp{$geoWithin:{$box:[[1,1],[2,2]]}}}) |
b.$center圆形,由圆心坐标和半径组成
1 | > db.number.find({sp{$geoWithin:{$center:[[1,1],5]}}}) |
c.polygon多边形,由多个点组成
1 | > db.number.find({sp{$geoWithin:{$polygon:[[1,1],[1,2],[2,2]]}}}) |
3.使用geoNear查询,要用runCommand命令
1 | > db.runCommand({geoNear:"number",near:[1,1],maxDistance:10,num:5}) |
查询集合number中距离点[1,1]不超过10的文档,限制返回5条。返回结果:
1 | { |
2dsphere索引
2dsphere索引是球面地理位置索引
创建方式
1 | > db.number.ensureIndex({sp:"2dsphere"}) |
位置信息是GeoJson数据结构,GeoJson的格式是{type:"GeoJSON type",coordinates:"coordinates"}
1 | > db.number.insert({sp:{type:"Point",coordinates:[1,1]}}) |
查询方式与2d索引相似,但2dsphere索引支持$minDistance最小距离
索引属性
几个重要的属性
1、name名字
可以给索引自定义名字,名字大小有123字节的限制,可以根据name删除索引
1 | > db.namber.ensureIndex({x:1},"myname") |
2、unique唯一性
unique默认值为false,当其值为true时,不能插入两条规定字段一样的数据,可以避免重复插入
1 | > db.number.ensureIndex({x:1},{unique:true}) |
两个文档x字段的键值不会重复,重复的文档无法插入
3、sparse稀疏性
sparse默认false,即MongoDB默认是不稀疏的,如需要给y字段创建索引,而文档{x:1}没有y字段的也会添加y字段创建索引。当sparse为true时,不会为文档不存在的字段创建索引
1 | > db.number.ensureIndex({y:1},{sparse:true}) |
只为有字段y的文档创建索引$exists
可以指定查询某字段存在或不存在的文档,值为true时存在指定字段的文档,false查询不存在指定字段的文档。使用$exists
可以来验证:sparse为true时,只为存在指定字段的文档创建索引
hint()方法强制使用某个索引
1 | > db.number.getIndexes() |
在没有y字段的文档中强制使用y_1稀疏索引查询,但没有y字段的文档同时也没有y_1稀疏索引,因而无返回数据
4、expirAfterSeconds过期性
过期索引就是使用这个属性,expirAfterSeconds后直接添加大于60(秒)的时间限制
索引构建分析
好处:加快索引相关的查询
缺点:增加磁盘空间的消耗,降低写入性能
评判当前索引构建情况
1.mongostat工具
2.profile集合
3.日志
4.explain分析
mongostat工具
会间隔固定时间获取mongodb的当前运行状态,如果发现数据库突然变慢或者有其他问题的话,立刻考虑采用mongostat来查看mongo的状态
1 | D:\mongodb\bin>mongostat -h 127.0.0.1 |
输出参数
inserts 每秒插入数量
query 每秒查询数量
update 每秒更新数量
delete 每秒删除数量
getmore 每秒执行getmore次数
command 每秒的命令数,比以上插入、查找、更新、删除的综合还多,还统计了别的命令
flushs 每秒执行fsync将数据写入硬盘的次数
mapped 所有的被mmap的数据量,单位是MB
vsize 虚拟内存使用量,单位MB
res 物理内存使用量,单位MB
faults 内存换页时间
locked 被锁的时间百分比
idx miss % 索引未命中百分比
qr|qw 读写队列
ar|aw 活跃的客户端连接数
netIn 网卡输入流量
netOut 网卡输出流量
conn 当前连接到mongodb的数量
time 当前状态的时间
当idx miss %
的值变高时,会使qr|qw
也变高。如果idx miss %
和qr|qw
比较高说明MongoDB性能有问题
profile
查看profile状态
1 | > db.getProfilingStatus() |
was:profile记录级别。共有0、1、2三个级别,0是关闭记录,1是记录慢查询,2是记录所有
slowns:慢查询阀值
查询profile记录级别
1 | > db.getProfilingLevel() |
设置profile记录级别
1 | > db.getProfilingLevel(1) |
查看profile文件,使用$natural自然排序,返回记录的最近一次操作情况
1 | > db.getProfilingLevel(2) #记录所有操作 |
日志
日志和profile类似也会记录系统相应的使用情况,并且能够配置日志的记录情况。verbose参数用来记录日志详细状态,v越多越详细
1 | #mongod.conf |
explain分析
用于查看设置索引后,是否起作用
1 | > db.number.ensureIndex({m:1}) |
返回的数据中,参数millis表示用时,单位毫秒
安全问题
1.最安全的是物理隔离,但不现实
2.网络隔离
3.防火墙
4.用户名、密码
创建用户
配置mongod.conf文件,添加auth = true
1 | use={ |
角色类型:内建类型
read 读取权限
readWrite 读写权限,不能操作索引
bdAdmin 操作数据库类型权限
dbOwner 具有前三者的权限
userAdmin 管理用户的权限
用户角色:
1.数据库角色(read,readWrite,dbAdmin,dbOwner,userAdmin)
2.集群角色(clusterAdmin,clusterManager,…)
3.备份角色(backup,restore,…)
4.其他特殊权限(DBAdminAnyDatabase,…)