MongoDB 基础

1. NoSQL 简介

NoSQL(NoSQL = Not Only SQL ),意即”不只仅是SQL”。html

在现代的计算系统上天天网络上都会产生庞大的数据量。linux

这些数据有很大一部分是由关系数据库管理系统(RDMBSs)来处理。 1970年 E.F.Codd’s提出的关系模型的论文 “A relational model of data for large shared data banks”,这使得数据建模和应用程序编程更加简单。git

经过应用实践证实,关系模型是很是适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。正则表达式

NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势愈加高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一律念无疑是一种全新的思惟的注入。sql

1.1 什么是NoSQL

NoSQL,指的是非关系型的数据库。NoSQL有时也称做Not Only SQL的缩写,是对不一样于传统的关系型数据库的数据库管理系统的统称。 
对NoSQL最广泛的解释是”非关联型的”,强调Key-Value Stores和文档数据库的优势,而不是单纯的反对RDBMS。 
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook天天为他们的用户收集万亿比特的数据)。这些类型的数据存储不须要固定的模式,无需多余操做就能够横向扩展。
mongodb

 

1.2 为何使用NoSQL ?

今天咱们能够经过第三方平台(如:Google,Facebook等)能够很容易的访问和抓取数据。用户的我的信息,社交网络,地理位置,用户生成的数据和用户操做日志已经成倍的增长。咱们若是要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。shell

 

2. MongoDB简介

Mongodb由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。,是专为可扩展性,高性能和高可用性而设计的数据库, 是非关系型数据库中功能最丰富,最像关系型数据库的,它支持的数据结构很是散,是相似 json 的 bjson 格式,所以能够存储比较复杂的数据类型。数据库

MongoDB的(来自于英文单词“了Humongous”,中文含义为“庞大”)是能够应用于各类规模的企业,各个行业以及各种应用程序的开源数据库。做为一个适用于敏捷开发的数据库,MongoDB的的数据模式能够随着应用程序的发展而灵活地更新。编程

MongoDB 以一种叫作 BSON(二进制 JSON)的存储形式将数据做为文档存储具备类似结构的文档一般被整理成集合。能够把这些集合当作相似于关系数据库中的表: 文档和行类似, 字段和列类似。json

2.1 MongoDB数据格式

2.1.1 JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 JSON采用彻底独立于语言的文本格式,可是也使用了相似于C语言家族的习惯(包括C、 C++、 C#、 Java、JavaScript、 Perl、 Python等)。这些特性使JSON成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(通常用于提高网络传输速率)。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。

MongoDB 使用JSON(JavaScript ObjectNotation)文档存储记录。

JSON简单说就是JavaScript中的对象和数组,经过对象和数组能够表示各类复杂的结构。 
对象: 
对象在js中表示为“{}”括起来的内容,数据结构为 {key: value,key: value,…}的键值对的 
结构,在面向对象的语言中, key为对象的属性, value为对应的属性值,因此很容易理 
解,取值方法为 对象.key 获取属性值,这个属性值的类型能够是 数字、字符串、数组、 
对象几种。

例如: {"FirstName":"ke","LastName":"me","email":"hikeme@aa"}

取值方式和全部语言中同样,使用key获取,字段值的类型能够是 数字、字符串、数组、对象几种。

2.1.2 BSON

BSON是一种JSON的一种二进制形式的存储格式,简称Binary JSON,它和JSON同样,支持内嵌的文档对象和数组对象,可是BSON有JSON没有的一些数据类型,如Date和BinData类型 
它的优势是灵活性高,但它的缺点是空间利用率不是很理想。 
BSON有三个特色:轻量性、可遍历性、高效性。 
对JSON来讲,数据存储是无类型的,好比你要修改基本一个值,从9到10,因为从一个字符变成了两个,因此可能其后面的全部内容都须要日后移一位才能够。而使用BSON,你能够指定这个列为数字列,那么不管数字从9长到10仍是100,咱们都只是在存储数字的那一位上进行修改,不会致使数据总长变大。固然,在MongoDB中,若是数字从整形增大到长整型,仍是会致使数据总长变大的。

有时BSON相对JSON来讲也并无空间上的优点,好比对{“sex”:1},在JSON的存储上 
1只使用了一个字节,而若是用BSON,那就是至少4个字节

2.2 MongoDB 特色

高性能: Mongodb 提供高性能的数据持久性,尤为是支持嵌入式数据模型减小数据库系统上的 I/O操做,索引支持能快的查询,而且能够包括来嵌入式文档和数组中的键 
丰富的语言查询: Mongodb 支持丰富的查询语言来支持读写操做(CRUD)以及数据汇总,文本搜索和地理空间索引 
高可用性: Mongodb 的复制工具,成为副本集,提供自动故障转移和数据冗余, 
水平可扩展性: Mongodb 提供了可扩展性,做为其核心功能的一部分,分片是将数据分,在一组计算机上。 
支持多种存储引擎: WiredTiger 存储引擎和、 MMAPv1存储引擎和 InMemory 存储引擎

MongoDB Server 
是一个文档数据库,具备您须要的可扩展性和灵活性,丰富的查询和索引, 
当前最高稳定版本4.0

 

MongoDB Drivers 
官方MongoDB客户端库提供C, C ++, C#, Java, Node.JS, Perl, PHP,Python, Ruby和Scala驱动程序的参考指南。

MongoDB Stitch 
为开发人员提供了一个API到MongoDB和其余后端服务。保持MongoDB的所有功能和灵性,同时受益于强大的系统来配置细粒度的数据访问控制。

MongoDB Atlas 
MongoDB在云中部署,操做和扩展的最佳方式。适用于AWS,Azure和Google Cloud Platform。轻松将数据迁移到MongoDB Atlas,零停机

MongoDB Cloud Manager 
是一个用于管理MongoDB部署的软件包。 Ops Manager提供Ops Manager监控和Ops Manager备份,可帮助用户优化群集并下降操做风险

MongoDB Charts 
能够最快速最简单的建立Mongodb可视化图表

MongoDB Connector for BI 
MongoDB商业智能链接器(BI)容许用户使用SQL建立查询,并使用现有的关系商业智能工具(如Tableau, MicroStrategy和Qlik)对其MongoDB Enterprise数据进行可视化,图形化和报告。

MongoDB Compass 
经过从集合中随机抽样一个文档子集,为用户提供其MongoDB模式的图形视图。采样文件可最大程度地下降对数据库的影响,并能快速产生结果。有关 抽样的更多信息

MongoDB Spark Connector 
使用链接器,您能够访问全部使用MongoDB数据集的Spark库:用SQL进行分析的数据集(受益于自动模式推理),流式传输,机器学习和图形API。您也可使用链接器与Spark Shell。

 

3. MongoDB 安装

个人操做系统版本

[root@mongo-160 ~]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 

  

 官方文档手册

# 官方文档手册
https://docs.mongodb.com/manual/

  

我安装的是MongoDB 3.4 版本的,选择3.4版本查看相应手册

3.1 安装方式

我使用的是二进制包方式

3.2 目录规划

mongo软件以软链接形式放在/opt 目录下 
mongo数据存放目录存放在/data/mongo

3.3 软件安装

 

[root@mongo-160 ~]# mkdir -p /data/soft
[root@mongo-160 ~]# cd /data/soft/
[root@mongo-160 soft]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.20.tgz
[root@mongo-160 soft]# tar zxvf mongodb-linux-x86_64-3.4.20.tgz -C /opt/
[root@mongo-160 soft]# cd /opt/
[root@mongo-160 opt]# ln -s mongodb-linux-x86_64-3.4.20/ mongodb
[root@mongo-160 opt]# ll
total 0
lrwxrwxrwx. 1 root root 28 Jun  5 18:09 mongodb -> mongodb-linux-x86_64-3.4.20/
drwxr-xr-x. 3 root root 86 Jun  5 17:56 mongodb-linux-x86_64-3.4.20
# 为何作软连接了,之后后续版本作升级,
# 能够快速回滚到原来版本 这是最根本的
# 还能够作多实例


# 建立数据目录
[root@mongo-160 opt]# mkdir -p /data/mongodb
[root@mongo-160 opt]# mkdir -p /opt/mongodb/{conf,logs,pid}
[root@mongo-160 mongodb]# cd /opt/mongodb/
[root@mongo-160 mongodb]# ll
total 120
drwxr-xr-x. 2 root root  4096 Jun  5 17:56 bin
drwxr-xr-x. 2 root root     6 Jun  5 18:13 conf
-rw-r--r--. 1 root root 34520 Mar 13 06:02 GNU-AGPL-3.0
drwxr-xr-x. 2 root root     6 Jun  5 18:13 logs
-rw-r--r--. 1 root root 16726 Mar 13 06:02 MPL-2
drwxr-xr-x. 2 root root     6 Jun  5 18:13 pid
-rw-r--r--. 1 root root  2266 Mar 13 06:02 README
-rw-r--r--. 1 root root 55625 Mar 13 06:02 THIRD-PARTY-NOTICES

  

3.4 配置文件

mongodb.conf 配置文件是yaml格式的 
看看官方文档3.4版本的配置手册:

https://docs.mongodb.com/v3.4/reference/configuration-options/

  

个人环境配置文件以下:

[root@mongo-160 ~]# cat /opt/mongodb/conf/mongodb.conf
systemLog:
   destination: file #Mongodb 日志输出的目的地,指定一个 file 或者 syslog,若是指定 file,必须指定systemlog.path
   logAppend: true #当实例重启时,不建立新的日志文件,在老的日志文件末尾继续添加
   path: /opt/mongodb/logs/mongodb.log #日志路径
storage:
   dbPath: /data/mongodb #数据存储目录
   journal: #回滚日志
      enabled: true
   directoryPerDB: true #默认 false,不适用 inmemory engine
   wiredTiger:
      engineConfig:
         cacheSizeGB: 1 #将用于全部数据缓存的最大小
         directoryForIndexes: true #默认 false 索引集合 storage.dbPath 存储在数据单独子目录
processManagement: #使用处理系统守护进程的控制处理
   fork: true # fork and run in background 后台运行
   pidFilePath: /opt/mongodb/pid/mongod.pid # location of pidfile 建立 pid 文件
net:
   port: 27017 #监听端口
   bindIp: 127.0.0.1,10.0.0.160 #绑定 ip
#replication:
# oplogSizeMB: 1024 #复制操做日志的大小
# replSetName: xxx #副本集名称,同一个副本集的全部主机必须设置相同的名称

  

3.5 管理 mongo

3.5.1 启动和关闭 mongo
#开启mongo
[root@mongo-160 ~]# /opt/mongodb/bin/mongod -f /opt/mongodb/conf/mongodb.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 14662
child process started successfully, parent exiting

#检查是否有mongo进程
[root@mongo-160 ~]# ps aux | grep mongo
root      14662  0.9  2.1 942708 43296 ?        Sl   09:51   0:00 /opt/mongodb/bin/mongod -f /opt/mongodb/conf/mongodb.conf
root      14691  0.0  0.0 112644   948 pts/0    R+   09:53   0:00 grep --color=auto mongo

#检查mongo的端口号
[root@mongo-160 ~]# netstat -ntulp | grep mongo
tcp        0      0 10.0.0.160:27017        0.0.0.0:*               LISTEN      14662/mongod        
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      14662/mongod 

#检查mongo数据文件是否生成,没生成之前默认是空的
[root@mongo-160 ~]# cd /data/mongodb/
[root@mongo-160 mongodb]# ls
admin            journal  _mdb_catalog.wt  sizeStorer.wt  WiredTiger        WiredTiger.lock    WiredTiger.wt
diagnostic.data  local    mongod.lock      storage.bson   WiredTigerLAS.wt  WiredTiger.turtle

#关闭mongo
[root@mongo-160 mongodb]# /opt/mongodb/bin/mongod -f /opt/mongodb/conf/mongodb.conf --shutdown
killing process with pid: 14662

# 再次查看还有没有端口号,没有了
[root@mongo-160 mongodb]# netstat -ntulp | grep mongo

  

注意一下: 尽可能少用kill -9 

若是用kill 建议用

shell> kill -2 PID
  原理:-2表示向mongod进程发送SIGINT信号。这是终端等同于ctrl+c
或
shell> kill -4 PID
  原理:-4表示向mognod进程发送SIGTERM信号。
mongod进程收到SIGINT信号或者SIGTERM信号,会作一些处理
> 关闭全部打开的链接
> 将内存数据强制刷新到磁盘
> 当前的操做执行完毕
> 安全中止
  切忌kill -9

 

3.5.2 写入环境变量
[root@mongo-160 mongodb]# echo 'PATH=$PATH:/opt/mongodb/bin' >> /etc/profile
[root@mongo-160 mongodb]# tail -n 1 /etc/profile
PATH=$PATH:/opt/mongodb/bin
[root@mongo-160 mongodb]# source /etc/profile
#查看有哪些mongo命令,是否写入环境变量成功了,有就是成功了
[root@mongo-160 mongodb]# mongo
mongo         mongodump     mongofiles    mongooplog    mongoreplay   mongos        mongotop      
mongod        mongoexport   mongoimport   mongoperf     mongorestore  mongostat  
3.5.3 建立 hosts 解析
[root@mongo-160 ~]# echo "10.0.0.160 mongo-160" >> /etc/hosts
[root@mongo-160 ~]# ping mongo-160 
PING mongo-160 (10.0.0.160) 56(84) bytes of data.
64 bytes from mongo-160 (10.0.0.160): icmp_seq=1 ttl=64 time=0.060 ms
3.5.4 链接 mongo
# 开启mongo
[root@mongo-160 ~]# mongod -f /opt/mongodb/conf/mongodb.conf 

# 链接mongo 
[root@mongo-160 ~]# mongo mongo-160:27017
MongoDB shell version v3.4.20
connecting to: mongodb://mongo-160:27017/test
MongoDB server version: 3.4.20
Welcome to the MongoDB shell.
...
> exit
bye

  

3.5.5 mongo 终端中止服务

注意,关闭命令建议使用 mongo 内置的 db.shutdownServer()命令 
使用这条命令的前提是必须使用 localhost 登录mongo,不然会提示报错

[root@mongo-160 ~]# mongo localhost:27017
MongoDB shell version v3.4.20
connecting to: mongodb://localhost:27017/test
MongoDB server version: 3.4.20
...
> db.shutdownServer()
server should be down...
2019-06-06T10:37:38.205+0800 I NETWORK  [thread1] trying reconnect to localhost:27017 (127.0.0.1) failed
> exit
bye
[root@mongo-160 ~]# ps -ef | grep mongo
root      15258   2418  0 10:39 pts/0    00:00:00 grep --color=auto mongo

  

 

 

4.MongoDB 日志的警告信息

 

 

** WARNING: Access control is not enabled for the database.
**          Read and write access to data and configuration is unrestricted.
对数据库来讲访问控制是没有开启的,读取和写入数据和配置是不受限制的。须要咱们建立个用户,
开启认证。

** WARNING: You are running this process as the root user, which is not recommended.
不推荐以root用户来运行mongo 

** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
**        We suggest setting it to 'never'
** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
**        We suggest setting it to 'never'
自CentOS6版本开始引入了Transparent Huge Pages(THP),从CentOS7版本开始,该特性默认就会启用。尽管THP的本意是为提高内存的性能,不过某些数据库厂商仍是建议直接关闭THP(好比说Oracle、MariaDB、 MongoDB等),透明的Huge Pages可能会在运行时引发内存分配延迟。

查看THP的启动状态:

[root@mongo-160 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
[root@mongo-160 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
[always] madvise never

  

透明的大页(THP)是一种Linux内存管理系统,它能够减小机器w上的翻译后备缓冲区(TLB)查找的开销

always - always use THP
never - disable THP

  

运行如下命令即时禁用THP

[root@mongo-160 ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@mongo-160 ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
[root@mongo-160 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]
[root@mongo-160 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]

[root@mongo-160 ~]# chmod +x /etc/rc.d/rc.local 
[root@mongo-160 ~]# vim /etc/rc.d/rc.local
#添加以下两行内容
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

[root@mongo-160 ~]# tail -n 2 /etc/rc.d/rc.local 
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

5. MongoDB 的 CRUD操做

CRUD 操做是 create(建立), read(读取), update(更新)和 delete(删除) 文档 
MongoDB 3.x 不支持多文档事务(mongodb4.0 开始支持 )。可是 MongoDB 确实在一个文档上提供了原子操做。尽管集合中的文档一般都是相同的,可是 MongoDB 中的集合不须要指定 schema。 
MongoDB 不支持 SQL 可是支持本身的丰富的查询语言。 
在 MongoDB 中,存储在集合中的每一个文档都须要一个惟一的 _id 字段,做为主键。若是插入的文档省略了该_id 字段,则 MongoDB 驱动程序将自动为该字段生成一个 ObjectId_id。也用于经过更新操做插入的文档upsert: true.若是文档包含一个_id 字段,该_id 值在集合中必须是惟一的,以免重复键错误。 
在 MongoDB 中,插入操做针对单个集合。 MongoDB 中的全部写操做都是在单个文档的级别上进行的

5.1 一些帮助命令

help: 显示帮助。
db.help() 显示数据库方法的帮助。
db.<collection>.help() 显示收集方法的帮助, <collection>能够是现有的集合或不存在的集合的名称。
show dbs 打印服务器上全部数据库的列表。
use <db> 将当前数据库切换到<db>。该 mongoshell 变量 db 被设置为当前数据库。
show collections 打印当前数据库的全部集合的列表。
show users 打印当前数据库的用户列表。
show roles 打印用于当前数据库的用户定义和内置的全部角色的列表。
show profile 打印须要 1 毫秒或更多的五个最近的操做。有关详细信息,请参阅数据库分析器上的文档。
show databases 打印全部可用数据库的列表。

5.2 插入数据

官方文档:
https://docs.mongodb.com/v3.4/tutorial/insert-documents/

MongoDB提供了将文档插入到集合中的如下方法: 
db.collection.insertOne() 将单个文档插入到集合中。 
db.collection.insertMany() 将多个 文档插入到集合中。 
db.collection.insert() 将单个文档或多个文档插入到集合中。 
db.collection.save() 根据文档参数更新现有文档或插入新文档
  

5.2.1 单条插入

命令集合:

db.test.insert( {"name":"keme","age":18,"ad":"北京市朝阳区"} )
db.test.insert( {"name":"xiaoke","age":17,"ad":"北京市朝阳区"} )
db.test.insert( {"name":"aaa","age":20,"ad":"北京市朝阳区"} )
db.test.insert( {"name":"xiaoxi","age":21,"ad":"北京市朝阳区"} )
db.test.insert( {"name":"xiaojian","age":28,"ad":"北京市朝阳区","sex":"boy"} )

  

执行结果

登陆mongo
[root@mongo-160 ~]# mongo localhost:27017
>db.test.insert( {"name":"keme","age":18,"ad":"北京市朝阳区"} )
>db.test.insert( {"name":"xiaoke","age":17,"ad":"北京市朝阳区"} )
>db.test.insert( {"name":"aaa","age":20,"ad":"北京市朝阳区"} )
>db.test.insert( {"name":"xiaoxi","age":21,"ad":"北京市朝阳区"} )
>db.test.insert( {"name":"xiaojian","age":28,"ad":"北京市朝阳区","sex":"boy"} )

#查看插入结果
> db.test.find()
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"), "name" : "keme", "age" : 18, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afb"), "name" : "xiaoke", "age" : 17, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afc"), "name" : "aaa", "age" : 20, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afd"), "name" : "xiaoxi", "age" : 21, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4eceada13ff76c3afe"), "name" : "xiaojian", "age" : 28, "ad" : "北京市朝阳区", "sex" : "boy" }
5.2.2 多行插入

官方文档例子

#命令
db.inventory.insertMany( [
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);

执行结果

> db.inventory.insertMany( [
... { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
... { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
... { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
... { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
... { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
... ]);
{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("5cfdc5eaceada13ff76c3b02"),
        ObjectId("5cfdc5eaceada13ff76c3b03"),
        ObjectId("5cfdc5eaceada13ff76c3b04"),
        ObjectId("5cfdc5eaceada13ff76c3b05"),
        ObjectId("5cfdc5eaceada13ff76c3b06")
    ]
}

5.3 查询数据

db.collection.find(query , projection ) 
选择集合或视图中的文档,并将光标返回 到所选文档参数query类型是文件,可选的。用查询运算符指定选择过滤器要返回集合中的全部文档请忽略此参数或传递一个空的文档参数projection类型是文件,可选的。指定在与查询过滤器匹配的文档中返回的字段。要返回匹配文档中的全部字段, 返回: 一个光标匹配的文件query 标准。当find()方法“返回文档”时 
,该方法实际上将光标返回到文档。 
$or 或者关系, $in 匹配多个件键 
虽然可使用$or运算符来表达下面查询,但在同一字段上执行相等检查时,请使用$in运算符而不是$or运算符。

 

5.3.1 通常查询

查询全部 

db.<collection>.find()

查询单条 

db.<collection>.findOne()
> db.test.findOne()
{
    "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"),
    "name" : "keme",
    "age" : 18,
    "ad" : "北京市朝阳区"
}
5.3.2 条件查询

不少都是看官方文档

> myCursor = db.inventory.find( { status: "D" } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b04"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b05"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
# 至关于SQL语句的 select * from inventory where status="D";

  

示例2

# 这是找出json 里面的值 
> myCursor = db.inventory.find( { "size.uom": "in" } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b03"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b04"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }

 

示例3:and

> myCursor = db.inventory.find( { status: "A", qty: { $lt: 30 } } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b02"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
至关于sql 语句
select * from inventory where status="A" and qty< 30;

  

 

示例4:or  

> myCursor = db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b02"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b03"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b06"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }

至关于sql 语句:
select * from inventory where status=A or qty<30;

  

示例5:正则

myCursor = db.inventory.find( {status: "A",$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]} )
或者:
myCursor = db.inventory.find( {
status: "A",
$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )

执行结果

> myCursor = db.inventory.find( {
... status: "A",
... $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
... } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b02"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b06"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }

# 至关于sql语句
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")
5.3.3 比较运算符
  • $eq 匹配等于指定值的值。

  • $gt 匹配大于指定值的值。

  • $gte 匹配大于或等于指定值的值。

  • $in 匹配数组中指定的任何值。

  • $lt 匹配小于指定值的值。

  • $lte 匹配小于或等于指定值的值。

  • $ne 匹配不等于指定值的全部值。

  • $nin不匹配数组中指定的值。

  

5.3.4 逻辑查询运算符
  • $and 使用逻辑链接查询子句AND返回与两个子句的条件相匹配的全部文档。

  • $not 反转查询表达式的效果,并返回与查询表达式不匹配的文档。

  • $nor 使用逻辑链接查询子句NOR返回全部没法匹配两个子句的文档。

  • $or 使用逻辑链接查询子句OR返回与任一子句的条件相匹配的全部文档

  

5.4 更新数据

MongoDB提供如下方法来更新集合中的文档: 

db.collection.updateOne(<filter>, <update>, <options>)即便可能有多个文档经过过滤条件匹配到,可是也最多也只更新一个文档

db.collection.updateMany(<filter>, <update>, <options>) 更新全部经过过滤条件匹配到的文档

db.collection.replaceOne(<filter>, <replacement>, <options>) 即便可能有多个文档经过过滤条件匹配到,可是也最多也只替换一个文档

db.collection.update()即便可能有多个文档经过过滤条件匹配到,可是也最多也只更新或者替换一个文档。

示例1:更新单条数据  

db.inventory.updateOne(
{ "item" : "paper" }, // specifies the document to update
{
$set: { "size.uom" : "cm", "status" : "P" },
$currentDate: { "lastModified": true }
}
)

执行结果

> db.inventory.updateOne(
... { "item" : "paper" }, // specifies the document to update
... {
... $set: { "size.uom" : "cm", "status" : "P" },
... $currentDate: { "lastModified": true }
... }
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

# 查看更新是否成功
> myCursor = db.inventory.find( { "item": "paper" } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b04"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-06-10T03:32:31.190Z") }
更新成功了

 

示例2:更新多条数据

db.inventory.updateMany(
{ "qty" : { $lt: 50 } }, // specifies the documents to update
{
$set: { "size.uom" : "cm", "status": "P" },
$currentDate : { "lastModified": true }
}
)

执行结果

> db.inventory.updateMany(
... { "qty" : { $lt: 50 } }, // specifies the documents to update
... {
... $set: { "size.uom" : "cm", "status": "P" },
... $currentDate : { "lastModified": true }
... }
... )
{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
#查看修改的数据
> myCursor = db.inventory.find( { "qty": { $lt: 50 } } )
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b02"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-06-10T03:35:53.575Z") }
{ "_id" : ObjectId("5cfdc5eaceada13ff76c3b06"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-06-10T03:35:53.575Z") }

  

5.5 删除数据

MongoDB提供如下方法来删除集合的文档:

db.collection.remove() 删除单个文档或与指定过滤器匹配的全部文档。 参数{},清空集合 
db.collection.drop()此方法获取受影响的数据库上的写入锁定,并将阻止其余操做,直到 
其完成。 不加参数删除全部数据包括索引 
db.collection.deleteOne() 最多删除与指定过滤器匹配的单个文档,即便多个文档可能与指定的过滤器匹配。 
db.collection.deleteMany() 删除与指定过滤器匹配的全部文档。

示例

> show dbs
admin  0.000GB
local  0.000GB
test   0.000GB
> use test
switched to db test
> show collections
inventory
test

# 删除单条数据
db.inventory.deleteOne(
{ "status": "D" } // specifies the document to delete
)

# 删除多条数据
db.inventory.deleteMany(
{ "status" : "P" } // specifies the documents to delete
)

  

6. Mongodb 索引

默认状况下,建立索引将阻止数据库上的全部其余操做。在集合上构建索引时,保存集合的数据库对于读取或写入操做是不可用的,直到索引构建完成。任何须要对全部数据库(例如listDatabases)进行读或写锁定的操做将等待前台索引构建完成。

对于可能须要长时间运行的索引建立操做,能够考虑 background 选项,这样MongoDB数据库在索引建立期间仍然是可用的。例如,在 people 集合的 zipcode 键上建立一个索引,这个过程在后台运行,可使用以下方式:

db.people.createIndex( { zipcode: 1}, {background: true} )

默认 MongoDB 索引建立的 background 是 false

索引优化: db.test.find({“id”:100}).explain()

6.1 MongoDB 有哪些索引:

单键索引(Single Field Indexes): 
在一个键上建立的索引就是单键索引,单键索引是最多见的索引,如MongoDB默认建立的_id的索引就是单键索引。

复合索引(Compound Indexes): 
在多个键上创建的索引就是复合索引。

多键索引(Multikey Index): 
若是在一个数组上面建立索引, MongoDB会本身决定,是否要把这个索引建成多键索引。

地理空间索引(Geospatial Indexes and Queries): 
MongoDB支持几种类型的地理空间索引。其中最经常使用的是 2dsphere 索引(用于地球表面类型的地图)和 2d 索引(用于平面地图和时间连续的数据)经度和纬度。

2d: 
2d 索引用于扁平化表面,而不是球体表面,不然极点附近会出现大量的扭曲变形。

全文索引(Text Indexes): 
当文本块比较大的时候,正则表达式搜索会很是慢,并且没法处理语言理解的问题(如entry 和 entries 应该算是匹配的)。使用全文索引能够很是快地进行文本搜索,就如同内置了多种语言分词机制的支持同样。建立索引的开销都比较大,全文索引的开销更大。建立索引时,需后台或离线建立。

哈希索引(Hashed Index): 
哈希索引能够支持相等查询,可是哈希索引不支持范围查询。您可能没法建立一个带有哈希索引键的复合索引或者对哈希索引施加惟一性的限制。可是,您能够在同一个键上同时建立一个哈希索引和一个递增/递减(例如,非哈希)的索引,这样MongoDB对于范围查询就会自 
动使用非哈希的索引。

示例:建立一个索引

# 查看默认集合文档信息,也就是没有索引
> db.test.find()
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"), "name" : "keme", "age" : 18, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afb"), "name" : "xiaoke", "age" : 17, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afc"), "name" : "aaa", "age" : 20, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afd"), "name" : "xiaoxi", "age" : 21, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4eceada13ff76c3afe"), "name" : "xiaojian", "age" : 28, "ad" : "北京市朝阳区", "sex" : "boy" }

> db.test.find({"age":{ $lt: 20 }}).explain()
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.test",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "age" : {
                "$lt" : 20
            }
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "age" : {
                    "$lt" : 20
                }
            },
            "direction" : "forward"
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "mongo-160",
        "port" : 27017,
        "version" : "3.4.20",
        "gitVersion" : "447847d93d6e0a21b018d5df45528e815c7c13d8"
    },
    "ok" : 1
}

 

建立一个索引

> db.test.createIndex( {age:1} )
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

# 获得集合的全部索引
> db.test.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.test"
    },
    {
        "v" : 2,
        "key" : {
            "age" : 1
        },
        "name" : "age_1",
        "ns" : "test.test"
    }
]

  

再次查看执行计划

> db.test.find({"age":{ $lt: 20 }}).explain()

删除索引

> db.test.dropIndex( {age:1} )
{ "nIndexesWas" : 2, "ok" : 1 }

  

7 MongoDB 组件

官方文档:

https://docs.mongodb.com/v3.4/reference/program/

7.1 mongo

mongo 是MongoDB的交互式JavaScript shell接口,为系统管理员提供强大的界面,也为开发 
人员直接用数据库测试查询和操做的方式。 mongo还提供了一个功能齐全的JavaScript环境,与MongoDB一块儿使用。本文档介绍了mongoshell 的基本调用及其用法概述。

7.2 mongod

mongod 是 Mongodb 系统的主要守护进程,它处理数据请求,管理数据访问,并执行后台管理操做。启动进程指定配置文件,控制数据库的行为

7.3 mongos

mongos 对于“MongoDB Shard”,是用于处理来自应用层的查询的MongoDB分片配置的路由服务,并肯定此数据在分片集群中的位置, 以完成这些操做。从应用程序的角度来看,一个 mongos实例与任何其余MongoDB实例的行为相同。

7.4 mongostat

mongostat 实用程序能够快速概览当前正在运行的mongod 或mongos 实例的状态。mongostat在功能上相似于UNIX / Linux文件系统实用程序vmstat,但提供有关的数据 mongod和mongos实例。

[root@mongo-160 ~]# mongostat -h 10.0.0.160:27017
#若是开启用户认证:须要添加-u -p --authenticationDatabase=

 7.5 mongotop

mongotop提供了一种跟踪MongoDB实例读取和写入数据的时间量的方法。 mongotop 提供每一个收集级别的统计信息。默认状况下, mongotop每秒返回一次值

[root@mongo-160 ~]# mongotop -h 10.0.0.160:27017
若是开启用户认证:须要添加 -u -p --authenticationDatabase=

本身的实验机器没什么读写  

 

7.6 mongoplog

mongooplog是一个简单的工具,能够从远程服务器的复制 oplog轮询操做,并将其应用于本地服务器。此功能支持某些类型的实时迁移,这些迁移要求源服务器保持联机并在整个迁移过程当中运行。一般,此命令将采用如下形式:mongooplog - from mongodb0.example.net --host mongodb1.example.net

mongoperf是一种独立于MongoDB检查磁盘I / O性能的实用程序。它是随机磁盘I / O的测试 ,并呈现结果。  

例如:
echo “{nThreads: 16, fileSizeMB: 10000, r: true, w: true}” | mongoperf
在这个操做中:
mongoperf 测试直接物理随机读写io的,使用16个并发阅读器线程。
mongoperf 使用10 GB的测试文件。
或者参数写入文件里 mongoperf < config

  

7.7 mongoexport

mongoexport是一个实用程序,能够导出存储在MongoDB实例中的数据,生成一个JSON或 
CSV

# 导出test库下的test集合中 ,条件为 age 大于等于17 而且小于等于20 ,导出文件为test.json
[root@mongo-160 ~]# mongoexport -h 10.0.0.160:27017 -d test -c test -o test.json -q '{"age" : {$gte:17,$lte:20}}'
2019-06-10T16:46:32.312+0800    connected to: 10.0.0.160:27017
2019-06-10T16:46:32.312+0800    exported 3 records
# 查看导出的内容
[root@mongo-160 ~]# cat test.json 
{"_id":{"$oid":"5cfdbd4bceada13ff76c3afa"},"name":"keme","age":18.0,"ad":"北京市朝阳区"}
{"_id":{"$oid":"5cfdbd4bceada13ff76c3afb"},"name":"xiaoke","age":17.0,"ad":"北京市朝阳区"}
{"_id":{"$oid":"5cfdbd4bceada13ff76c3afc"},"name":"aaa","age":20.0,"ad":"北京市朝阳区"}

7.8 mongoimport

mongoimport工具从由其余第三方导出工具建立或可能的扩展JSON, CSV或TSV导出导入内容 

#导入到test库下的test集合,导入以前删除原来的集合
[root@mongo-160 ~]# mongoimport -d test -c test --type json --drop < test.json
2019-06-10T16:53:11.092+0800    connected to: localhost
2019-06-10T16:53:11.093+0800    dropping: test.test
2019-06-10T16:53:11.101+0800    imported 3 documents

避免使用mongoimport和mongoexport彻底实例生产备份。它们不可靠地保存全部丰富的 BSON数据类型,由于JSON只能表示BSON支持的类型的一个子集,使用该 –type=csv选项为输出指定CSV格式

7.9 bsondump

bsondump 转换BSON文件转换为咱们可直接读的格式,包括JSON。例如, 
bsondump对于读取mongodump输出文件颇有用。bsondump 是用于检查BSON文件的诊断工具,而不是用于数据摄取或其余应用程序使用的工具 
找个备份文件

# 我这没有bson 文件,先标注用法
shell> bsondump xxxx.bson > xxxx.json

mongofiles 实用程序能够从命令行操做在GridFS对象中存储在MongoDB实例中的文件。它特别有用,由于它提供了存储在文件系统和GridFS之间的对象之间的接口。

8. MongoDB 受权认证

官方文档:

https://docs.mongodb.com/v3.4/tutorial/enable-authentication/

8.1 受权介绍

认证是验证客户端身份的过程。当启用访问控制(即受权)时,MongoDB要求全部客户端进 
行身份验证,以肯定其访问。认证方法:为了验证用户,MongoDB提供了该 db.auth()方法。 
对于mongoshell和MongoDB工具,能够经过从命令行传入用户身份验证信息来验证用户,认证机制

MongoDB支持多种认证机制:  

  • SCRAM-SHA-1 
    3.0版中更改: 3.0中建立的新挑战响应用户将使用 SCRAM-SHA-1。若是使用2.6用户数据,MongoDB 3.0将继续使用MONGODB-CR。

  • x.509证书认证。

除了支持上述机制外,MongoDB Enterprise还支持如下机制

 

  • LDAP代理身份验证和Kerberos身份验证。

 

 

 

  • 内部认证

除了验证客户端的身份以外,MongoDB还能够要求副本集和分片集群的成员对其各自的副本

集或分片集群进行身份验证。有关 详细信息,请参阅分片集上的认证

在分片集群中,客户端一般直接对mongos实例进行身份验证 。可是,某些维护操做可能需

要直接对特定的分片进行身份验证。

 

 

 

用户管理界面 
要添加用户, MongoDB 提供了该 db.createUser()方法。添加用户时,您能够为用户分配色以授予权限。 

注意: 
在数据库中建立的第一个用户应该是具备管理其余用户的权限的用户管理员。 
你还能够更新现有用户,例如更改密码并授予或撤销角色 
  

认证数据库 
添加用户时,能够在特定数据库中建立用户。该数据库是用户的身份验证数据库。 
用户能够跨不一样数据库拥有权限; 即用户的权限不限于认证数据库。经过分配给其余数据库中的用户角色,在一个数据库中建立的用户能够具备对其余数据库的操做权限。 
用户名和认证数据库做为该用户的惟一标识符。也就是说,若是两个用户具备相同的名称, 
可是在不一样的数据库中建立,则它们是两个不一样的用户。若是您打算拥有具备多个数据库权 
限的单个用户,请在适用的数据库中建立具备角色的单个用户,而不是在不一样数据库中屡次 
建立用户。

一些相关方法

db.auth() 将用户验证到数据库。
db.changeUserPassword() 更改现有用户的密码。
db.createUser() 建立一个新用户。
db.dropUser() 删除单个用户。
db.dropAllUsers() 删除与数据库关联的全部用户。
db.getUser() 返回有关指定用户的信息。
db.getUsers() 返回有关与数据库关联的全部用户的信息。
db.grantRolesToUser() 授予用户角色及其特权。
db.removeUser() 已过期。从数据库中删除用户。
db.revokeRolesFromUser() 从用户中删除角色。
db.updateUser() 更新用户数据。
db.createRole() 建立角色并指定其特权。
db.dropRole() 删除用户定义的角色。
db.dropAllRoles() 删除与数据库关联的全部用户定义的角色。
db.getRole() 返回指定角色的信息。
db.getRoles() 返回数据库中全部用户定义角色的信息。
db.grantPrivilegesToRole() 将权限分配给用户定义的角色。
db.revokePrivilegesFromRole() 从用户定义的角色中删除指定的权限
db.grantRolesToRole() 指定用户定义的角色从中继承权限的角色。
db.revokeRolesFromRole() 从角色中删除继承的角色。
db.updateRole() 更新用户定义的角色

8.2 用户角色

8.2.1 数据库用户角色

 

  • read:提供对全部读取数据的能力非 -系统集合和下列系统集合: system.indexes, system.js和 system.namespaces收藏。该角色经过授予如下操做来提供读访问权限:
  • readWrite:提供read角色的全部权限以及修改全部非系统集合和system.js集合上的数据的功能。

 

8.2.3 数据库管理角色

dbAdmin, dbOwner, userAdminAnyDatabase 
提供在当前数据库上建立和修改角色和用户的功能。该角色还间接地提供 对数据库的超级用户访问,或者若是做用于admin数据库的集群。该userAdmin角色容许用户授予任何用户任何特权,包括本身。

8.2.4 集群管理角色

该admin数据库包括用于管理整个系统,而不只仅是一个单一的数据库如下角色。这些角色包括但不限于复制集和分片集群管理功能。

  • clusterAdmin :提供最大的集群管理访问。这个角色组合由授予的权限clusterManager, clusterMonitor和hostManager角色。另外,角色提供了dropDatabase动做。

  • clusterManager : 在集群上提供管理和监控动做。具备该角色的用户能够访问config和local数据库,其在分片和复制所使用的

8.2.5 内部角色
  • __system: MongoDB将此角色分配给表示集群成员的用户对象,如副本集成员和mongos实例。角色受权其持有人对数据库中的任何对象采起任何行动
8.2.6 自定义角色
# 建立角色
db.createRole( { role: “test”, privileges: [ { resource: { db: “test”, collection: “” }, actions: [ “insert”,“update”,remove] }, ], roles: [ { role: “read”, db: “test” } ] }, { w: “majority” , wtimeout: 5000 })
# 建立用户,添加到相应角色
db.createUser({user:"ke",pwd:"123456",roles:[ { role:"test", db:"test" }]})

#上面自定义角色这个模拟的语法示例,没在实验环境作演示

8.3 建立用户和角色

[root@mongo-160 ~]# mongo localhost:27017
#查看当前mongo实例有哪些用户
> db.getUsers()
[ ]
空的,没有用户

# 建立用户
> db.createUser({user: "admin",pwd: "123456",roles:[ { role: "root", db:"admin"}]})
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}
# 查看用户
> db.getUsers()
[
    {
        "_id" : "test.admin",
        "user" : "admin",
        "db" : "test",
        "roles" : [
            {
                "role" : "root",
                "db" : "admin"
            }
        ]
    }
]

8.4 用户认证配置文件

末尾添加以下两行内容
[root@mongo-160 ~]# vim /opt/mongodb/conf/mongodb.conf 
security: #认证
   authorization: enabled #启用或者禁用基于角色的访问控制来管理每一个用户对数据库资源和操做的访问enabled 或者 disables

#重启生效
[root@mongo-160 ~]# mongod -f /opt/mongodb/conf/mongodb.conf --shutdown
killing process with pid: 79647
[root@mongo-160 ~]# mongod -f /opt/mongodb/conf/mongodb.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 93037
child process started successfully, parent exiting

 

8.5 使用帐号密码链接MongoDB

配置问权限认证后须要重启节点,再次登录若是不使用帐号密码就查看不了数据

[root@mongo-160 ~]# mongo localhost:27017 -u admin -p123456
> show dbs
admin  0.000GB
local  0.000GB
test   0.000GB

 

设置不一样帐号权限

# 用admin用户 建立一个schools 库, 建立一个students集合,插入一条数据
> use school
switched to db school
> show collections
> db.students.insert ( {"name":"keme"} )
WriteResult({ "nInserted" : 1 })
# 查看集合
> show collections
students

而后建立不一样帐号权限  

use test
# 建立一个用户keme,在test 数据库下有读写, 在school 下只有读取
db.createUser(
{
user: "keme",
pwd: "123456",
roles: [ { role: "readWrite", db: "test" },
{ role: "read", db: "school" } ]
}
)

执行结果

> use test
switched to db test
> db.createUser(
... {
... user: "keme",
... pwd: "123456",
... roles: [ { role: "readWrite", db: "test" },
... { role: "read", db: "school" } ]
... }
... )
Successfully added user: {
    "user" : "keme",
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "test"
        },
        {
            "role" : "read",
            "db" : "school"
        }
    ]
}

 

登录keme用户查看  

  

> use test
switched to db test
> db.auth("keme","123456")
1
> show collections
inventory
test
# 验证读
> db.test.findOne()
{
    "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"),
    "name" : "keme",
    "age" : 18,
    "ad" : "北京市朝阳区"
}

# 验证写
> db.test.insertOne( {"name":"xiaojian","age":20,"ad":"北京市朝阳区"} )
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5cff09d8ad4a9f4bf7ffb242")
}
# 切换到 school 库,发现可读不可写
> use school
switched to db school
#读取
> db.students.findOne()
{ "_id" : ObjectId("5cff0753ad4a9f4bf7ffb241"), "name" : "keme" }
#写入,报错
> db.students.insert( {"name":"xiaoke"} )
WriteResult({
    "writeError" : {
        "code" : 13,
        "errmsg" : "not authorized on school to execute command { insert: \"students\", documents: [ { _id: ObjectId('5cff0a46ad4a9f4bf7ffb243'), name: \"xiaoke\" } ], ordered: true }"
    }
})

 

9. mongod 运维

9.1 数据备份

简单的导入导出能够用mongoexport 和 mongoimport

9.1.2 mongodump 备份工具

mongodump的参数与mongoexport的参数基本一致 
经常使用参数

参数                 参数说明
-h                  指明数据库宿主机的IP
-u                  指明数据库的用户名
-p                  指明数据库的密码
-d                  指明数据库的名字
-c                  指明collection的名字
-o                  指明到要导出的文件名
-q                  指明导出数据的过滤条件
--authenticationDatabase  验证数据的名称
--gzip              备份时压缩

举例:

# 建立一个备份目录点
[root@mongo-160 ~]# mkdir  -p /data/backup/mongo/
[root@mongo-160 ~]# mongo 10.0.0.160:27017 -u admin -p 123456
>use admin
#建立相应的管理用户
>db.createUser(
  {
    user: "kemeadmin",
    pwd: "123456",
    roles: [ { role: "root", db: "admin" } ]
   }
   )
> exit
bye

#进行全备
[root@mongo-160 ~]# mongodump -h 10.0.0.160:27017 -u kemeadmin -p123456 --authenticationDatabase admin -o /data/backup/mongo/full20190611
#查看是否备份成功
[root@mongo-160 ~]# cd /data/backup/mongo/full20190611/
[root@mongo-160 full20190611]# ls
admin  school  test
[root@mongo-160 full20190611]# cd test/
[root@mongo-160 test]# ls
inventory.bson  inventory.metadata.json  test.bson  test.metadata.json
[root@mongo-160 test]# pwd
/data/backup/mongo/full20190611/test

备份某个库

# 备份test 库
mongodump -h 10.0.0.160:27017 -u kemeadmin -p123456 --authenticationDatabase admin  -d test -o /data/backup/mongo
[root@mongo-160 ~]# cd /data/backup/mongo/
[root@mongo-160 mongo]# ls
full20190611  test
[root@mongo-160 mongo]# cd test/
[root@mongo-160 test]# ls
inventory.bson  inventory.metadata.json  test.bson  test.metadata.json

# 备份test库下的inventory 集合
[root@mongo-160 ~]# mongodump -h 10.0.0.160:27017 -ukemeadmin -p123456  --authenticationDatabase admin  -d test -c inventory -o /data/backup/mongo/

压缩备份

#压缩备份单个库
[root@mongo-160 ~]# mongodump -h 10.0.0.160:27017 -ukemeadmin -p123456 --authenticationDatabase admin  -d school -o /data/backup/mongo/ --gzip
# 压缩备份某个集合也是同样的加上--gzip

9.2 数据恢复

9.2.1 mongorestore 恢复

mongorestore与mongoimport参数相似 
经常使用参数以下:
  

参数      参数说明

-h          指明数据库宿主机的IP
-u          指明数据库的用户名
-p          指明数据库的密码
-d          指明数据库的名字
-c          指明collection的名字
-o          指明到要导出的文件名
-q          指明导出数据的过滤条件
--authenticationDatabase    验证数据的名称
--gzip      备份时压缩

--drop      恢复的时候把以前的集合drop掉

全库备份中恢复单库(基于以前的全库备份)

# 从全库中恢复test库
[root@mongo-160 ~]# mongorestore -h 10.0.0.160:27017 -ukemeadmin -p123456 --authenticationDatabase admin -d test --drop  /data/backup/mongo/full20190611/test

  

恢复某个库,不删除以前的集合看看数据有什么变化

作以前删除一条数据,好验证
> use test
switched to db test
> db.test.find()
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"), "name" : "keme", "age" : 18, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afb"), "name" : "xiaoke", "age" : 17, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afc"), "name" : "aaa", "age" : 20, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cff09d8ad4a9f4bf7ffb242"), "name" : "xiaojian", "age" : 20, "ad" : "北京市朝阳区" }
# 删除名字是aaa的数据
> db.test.deleteOne( {"name":"aaa"} )
{ "acknowledged" : true, "deletedCount" : 1 }
> db.test.find()
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"), "name" : "keme", "age" : 18, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afb"), "name" : "xiaoke", "age" : 17, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cff09d8ad4a9f4bf7ffb242"), "name" : "xiaojian", "age" : 20, "ad" : "北京市朝阳区" }

恢复test库,看看有没有aaa这个数据
[root@mongo-160 ~]# mongorestore -h 10.0.0.160:27017 -ukemeadmin -p123456 --authenticationDatabase admin -d test /data/backup/mongo/full20190611/test/
#登陆查看
[root@mongo-160 ~]# mongo localhost:27017 -uadmin -p123456
> use test
switched to db test
> db.test.find()
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afa"), "name" : "keme", "age" : 18, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afb"), "name" : "xiaoke", "age" : 17, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cff09d8ad4a9f4bf7ffb242"), "name" : "xiaojian", "age" : 20, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cfdbd4bceada13ff76c3afc"), "name" : "aaa", "age" : 20, "ad" : "北京市朝阳区" }
ok ,恢复成功

mongoexport/mongoimport与mongodump/mongorestore的对比

  • mongoexport/mongoimport导入/导出的是JSON格式,而mongodump/mongorestore导入/导出的是BSON格式。

  • JSON可读性强但体积较大,BSON则是二进制文件,体积小但对人几乎没有可读性。

  • 在一些mongodb版本之间,BSON格式可能会随版本不一样而有所不一样,因此不一样版本之间用mongodump/mongorestore可能不会成功,具体要看版本之间的兼容性。当没法使用BSON进行跨版本的数据迁移的时候,使用JSON格式即mongoexport/mongoimport是一个可选项。跨版本的mongodump/mongorestore并不推荐,实在要作请先检查文档看两个版本是否兼容(大部分时候是的)。

  • JSON虽然具备较好的跨版本通用性,但其只保留了数据部分,不保留索引,帐户等其余基础信息。使用时应该注意。

9.3 备份恢复小结

备份不是想我那样写的那么简单,我上面只写了一些工具的用法,一些平常的维护。从长远考虑,还须要考虑更多 
能够看看阿里云的云mongodb 一些备份恢复文档

https://help.aliyun.com/document_detail/55008.html?spm=a2c4g.11186623.6.677.4039d6afePr5YU

9.4 MongoDB 监控

监控及时得到应用的运行状态信息,在问题出现时及时发现。 
监控哪些

CPU、内存、磁盘I/O、应用程序(MongoDB)、进程监控(ps -aux)、错误日志监控

一些内部状态能够查看:  

db.serverStatus()
查看实例运行状态(内存使用、锁、用户链接等信息) 经过比对先后快照进行性能分析
"connections"     # 当前链接到本机处于活动状态的链接数
"activeClients"   # 链接到当前实例处于活动状态的客户端数量
"locks"           # 锁相关参数
"opcounters"      # 启动以后的参数
"opcountersRepl"  # 复制想关
"storageEngine"   # 查看数据库的存储引擎
"mem"             # 内存相关


db.stats()
显示信息说明:
"db" : "test" ,表示当前是针对"test"这个数据库的描述。想要查看其余数据库,能够先运行$ use databasename(e.g  $use admiin).

"collections" : 3,表示当前数据库有多少个collections.能够经过运行show collections查看当前数据库具体有哪些collection.

"objects" : 5,表示当前数据库全部collection总共有多少行数据。显示的数据是一个估计值,并非很是精确。

"avgObjSize" : 36,表示每行数据是大小,也是估计值,单位是bytes
"dataSize" : 468,表示当前数据库全部数据的总大小,不是指占有磁盘大小。单位是bytes
"storageSize" : 13312,表示当前数据库占有磁盘大小,单位是bytes,由于mongodb有预分配空间机制,为了防止当有大量数据插入时对磁盘的压力,所以会事先多分配磁盘空间。
"numExtents" : 3,彷佛没有什么真实意义。我弄明白以后再详细补充说明。
"indexes" : 1 ,表示system.indexes表数据行数。
"indexSize" : 8192,表示索引占有磁盘大小。单位是bytes
 "fileSize" : 201326592,表示当前数据库预分配的文件大小,例如test.0,test.1,不包括test.ns。
9.4.1 mongostat 工具

mongostat在功能上相似于UNIX / Linux文件系统实用程序vmstat

参数          参数说明
insert      每秒插入量
query       每秒查询量
update      每秒更新量
delete      每秒删除量
conn        当前链接数
qr|qw       客户端查询排队长度(读|写)最好为0,若是有堆积,数据库处理慢。
ar|aw       活跃客户端数量(读|写)
time        当前时间
9.4.2 mongotop

mongotop提供了一种跟踪MongoDB实例读取和写入数据的时间量的方法。

[root@mongo-160 ~]# mongotop -h 10.0.0.160:27017 -ukemeadmin -p123456 --authenticationDatabase admin

参数说明: 
ns:数据库命名空间,后者结合了数据库名称和集合。 
total:mongod在这个命令空间上花费的总时间。 
read:在这个命令空间上mongod执行读操做花费的时间。 
write:在这个命名空间上mongod进行写操做花费的时间。

9.4.3 db 级别命令
db.currentOp()
查看数据库当前执行什么操做。
  用于查看长时间运行进程。
  经过(执行时长、操做、锁、等待锁时长)等条件过滤。
  若是发现一个操做太长,把数据库卡死的话,能够用这个命令杀死他:> db.killOp()
db.serverStatus()
db.stats()

 

10. 小结

  • 禁止内存大页和root 用户操做

  • 源码包安装(二进制)

  • 备份、可能的话不一样机房备份

  • 开启认证、自定义角色、权限最小化、防火墙限制IP

  • 索引后台建立,去掉程序用户建立索引权限

  • 后台操做最好在业务低峰期

  • 数据库监控

其实上面我全是用root 用户登陆操做的,这只是为了我本身环境操做方便。应该有专门的程序用户来操做和管理mongodb应用。  

相关文章
相关标签/搜索