首页 > 数据库技术 > 详细

mongoDB初识01

时间:2020-08-19 21:57:48      阅读:84      评论:0      收藏:0      [点我收藏+]

mongoDB学习

数据

数据(英语:data),是指未经过处理的原始记录。
  一般而言,数据缺乏组织及分类,无法明确的表达事物代表的意义,它可能是一堆的杂志、一大叠的报纸、数种的开会记录或是整本病人的病历纪录。‘数据描述事物的符号记录‘,是可定义为意义的实体,涉及事物的‘存在形式‘。是关于事件之一组离散且客观的事实描述,是构成讯息和知识的原始材料
  

数据库管理系统

‘数据库管理系统‘(英语:database management system,缩写:DBMS) 是一种针对对象数据库,为管理数据库而设计的大型电脑软件管理系统。

  具有代表性的数据管理系统有:Oracle、Microsoft SQL Server、Access、MySQL及PostgreSQL等。通常数据库管理师会使用数据库管理系统来创建数据库系统。

  现代DBMS使用不同的数据库模型追踪实体、属性和关系。在个人电脑、大型计算机和主机上应用最广泛的数据库管理系统是关系型DBMS(relational DBMS)。在关系型数据模型中,用‘二维表格‘表示数据库中的数据。这些表格称为‘关系‘。

  数据库管理系统主要分为俩大类:RDBMS、NOSQL

更多

一、NoSQL介绍

1.NoSQL 简介

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",指的是非关系型的数据库,是对不同于传统的关系型数据库的数据库管理系统的统称。 

两者存在许多显著的不同点,其中最重要的是NoSQL不使用SQL作为查询语言。其数据存储可以不需要固定的表格模式,也经常会避免使用SQL的JOIN操作,一般有‘水平可扩展性‘的特征。

在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDMBSs)来处理,也有一部分使用非系型数据库处理

对NoSQL最普遍的解释是"非关联型的",强调Key-Value Stores和文档数据库的优点,而不是单纯的反对RDBMS。 

NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

2.为什么使用NoSQL

关系型数据库对数据要求严格,而非关系型数据库没有那么严格,对于大量‘不同字段‘的数据,存储更加方便

#优点
高可扩展性、分布式计算、没有复杂的关系、低成本
架构灵活、半结构化数据

#缺点
多表关联: 仅仅支持Left Outer Join
SQL 语句支持: 查询为主,部分支持
多表原子事务: 不支持
多文档原子事务:不支持
16MB 文档大小限制,不支持中文排序 ,服务端 Javascript 性能欠佳

二、MongoDB简介

MongoDB是什么

技术分享图片

    MongoDB并非芒果的意思,而是源于 Humongous(巨大)一词。

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

JSON 数据格式与语言无关,脱胎于 JavaScript
BSON是由10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式。BSON基于JSON格式,选择JSON进行改造的原因主要是JSON的通用性及JSON的schemaless的特性。

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

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

json格式:{key:value,key:value}
bjson格式:{key:value,key:value}
#区别在于:对于数据{id:1},在JSON的存储上1只使用了一个字节,而如果用BJSON,那就是至少4个字节

技术分享图片

MySQL与mongoDB对比

1)结构对比

mysql MongoDB
集合
字段 键值
文档

1)数据库中数据(student库,user表)

uid name age
1 zhangyu 18
2 chencgheng 28

2)mongoDB中的数据(student库,user集合)

1) {uid:1,name:zhangyu,age:18}
2) {uid:2,name:chencgheng,age:28}

3)区别总结

1.数据结构不同
2.数据库添加不存在字段的数据时报错
3.mongoDB‘可以添加‘不存在的字段的数据
4.mongoDB‘不需要提前创建好库和表‘,创建数据直接会帮助我们创建好

2.MongoDB 特点

1.高性能:
    Mongodb 提供高性能的数据‘持久性‘,‘索引‘支持更快的查询

2.丰富的语言查询:
    Mongodb 支持丰富的查询语言来‘支持读写‘操作(增删改查)以及数据汇总

3.高可用性: 
    Mongodb 的复制工具,称为‘副本集‘,提供自动故障转移和数据冗余(等于mysql的主从) 

4.水平可扩展性:
    Mongodb 提供了‘可扩展性‘,作为其核心功能的一部分,‘分片‘是将数据分在一组计算机上。

5.支持多种存储引擎: 
    WiredTiger存储引擎和、 MMAPv1存储引擎和 InMemory 存储引擎
    3.0以上版本            3.0以下版本
    新的引擎压缩比特别大,原来100个G,可能升级之后所有数据都在,只占用10个G
    
6.强大的索引支持:
    地理位置索引可用于构建 各种 O2O 应用、文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求

集群

1.自动复制和故障切换
多数据中心支持滚动维护无需关机支持最多50个成员
2.水平扩展
这种方式是目前构架上的主流形式,指的是通过增加服务器数量来对系统扩容。在这样的构架下,单台服务器的配置并不会很高,可能是配置比较低、很廉价的 PC,每台机器承载着系统的一个子集,所有机器服务器组成的集群会比单体服务器提供更强大、高效的系统容载量
3.分片集群架构如下图

技术分享图片

各存储引擎的对比

MySQL InnoDB MySQL NDB Oracle MongoDB MAPI MongoDB WiredTiger
事务 YES YES YES NO NO
锁粒度 ROW-level ROW-level ROW-level Collection-level Document-level
Geospatial YES YES YES YES YES
MVCC YES NO YES NO NO
Replication YES YES YES YES YES
外键 YES YES(From 7.3) YES NO NO
数据库集群 NO YES YES YES YES
B-TREE索引 YES YES YES YES YES
全文检索 YES NO YES YES YES
数据压缩 YES NO YES NO YES
存储限制 64TB 384EB NO NO NO
表分区 YES YES YES YES (分片) YES (分片)

MongoDB应用场景

1.游戏场景:
    使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新

2.物流场景:
    使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。

3.社交场景:
    使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
    将送快递骑手、快递商家的信息(包含位置信息)存储在 MongoDB,然后通过 MongoDB 的地理位置查询,这样很方便的实现了查找附近的商家、骑手等功能,使得快递骑手能就近接单
    地图软件、打车软件、外卖软件,MongoDB强大的地理位置索引功能使其最佳选择

4.物联网场景:
    使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析

5.视频直播:
    使用 MongoDB 存储用户信息、礼物信息等

6.电商场景:
    上衣有胸围,裤子有腰围,如果用数据库需要分成两个库,如果使用MongoDB都可以存在一起
    
    

什么时候该MongDB

应用特征 Yes/No?
我的数据量是有亿万级或者需要不断扩容
需要2000-3000以上的读写每秒
新应用,需求会变,数据模型无法确定
我需要整合多个外部数据源
我的系统需要99.999%高可用
我的系统需要大量的地理位置查询
我的系统需要提供最小的latency
我要管理的主要数据对象<10

在上面的表格中进行选择,但有1个yes的时候:可以考虑MongoDB;当有2个以上yes的时候:不会后悔的选择!

MongoDB慎用场景

慎用场景 原因
PB 数据持久存储大数据分析数据湖 Hadoop、Spark提供更多分析运算功能和工具,并行计算能力更强MongoDB + Hadoop/Spark
搜索场景:文档有几十个字段,需要按照任意字段搜索并排序限制等 不建索引查询太慢,索引太多影响写入及更新操作
ERP、CRM或者类似复杂应用,几十上百个对象互相关联** 关联支持较弱,事务较弱
需要参与远程事务,或者需要跨表,跨文档原子性更新的 MongoDB 事务支持仅限于本机的单文档事务
100% 写可用:任何时间写入不能停 MongoDB换主节点时候会有短暂的不可写设计所限

三、MongoDB安装部署

环境

[root@db02 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core) 
[root@db02 ~]#  uname -r
3.10.0-957.el7.x86_64
[root@db02 ~]# hostname -I
10.0.0.52 172.16.1.52 
[root@db02 ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon

0.安装依赖

[root@redis01 ~]# yum install -y libcurl openssl

1.上传或下载包

#下载地址:
https://www.mongodb.com/dr/fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.9-rc0.tgz/download
[root@redis01 ~]# rz mongodb-linux-x86_64-3.6.13.tgz 

2.解压包

[root@redis01 ~]# tar xf mongodb-linux-x86_64-3.6.13.tgz -C /usr/local/
[root@redis01 ~]# ln -s /usr/local/mongodb-linux-x86_64-3.6.13 /usr/local/mongodb

3.配置

#创建目录
[root@redis01 ~]# mkdir /server/mongo_27017/{conf,logs,pid,data} -p

#配置
[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf
systemLog:
  destination: file   
  logAppend: true  
  path: /server/mongo_27017/logs/mongodb.log

storage:
  journal:
    enabled: true
  dbPath: /server/mongo_27017/data
  directoryPerDB: true
  wiredTiger:
     engineConfig:
        cacheSizeGB: 1
        directoryForIndexes: true
     collectionConfig:
        blockCompressor: zlib
     indexConfig:
        prefixCompression: true

processManagement:
  fork: true
  pidFilePath: /server/mongo_27017/pid/mongod.pid

net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.53
  
  
#配置详解
#日志相关
systemLog:
  #以文件格式存储
  destination: file
  #每次重启,不生成新文件,每次都追加到文件
  logAppend: true
  #指定文件路径
  path: /server/mongo_27017/logs/mongodb.log

#数据部分
storage:
  #数据回滚。类似于mysql的undolog
  journal:
    enabled: true
  #数据目录
  dbPath: /server/mongo_27017/data
  #默认 false,不适用 inmemory engine
  directoryPerDB: true
  #存储引擎
  wiredTiger:
     #存储引擎设置
     engineConfig:
        #想把数据存到缓存,缓存的大小
        cacheSizeGB: 1
        #设置一个库就是一个目录,关闭就全放到一个目录下,很乱
        directoryForIndexes: true
     collectionConfig:
        blockCompressor: zlib
     #压缩相关
     #索引压缩(与压缩一起使用)
     indexConfig:
        prefixCompression: true
#守护进程的模式
processManagement:
  fork: true
  #指定pid文件
  pidFilePath: /server/mongo_27017/pid/mongod.pid
#指定端口和监听地址
net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.53

4.启动

[root@redis01 ~]# /usr/local/mongodb/bin/mongod -f /server/mongo_27017/conf/mongodb.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 11547
child process started successfully, parent exiting

#验证启动
[root@redis01 ~]# ps -ef | grep mongo
root      11547      1  6 08:48 ?        00:00:00 /usr/local/mongodb/bin/mongod -f /server/mongo_27017/conf/mongodb.conf

5.配置环境变量

[root@redis01 ~]# vim /etc/profile.d/mongodb.sh
export PATH="/usr/local/mongodb/bin:$PATH"

[root@redis01 ~]# source /etc/profile

四、mongo登录警告处理

1.警告一

#访问设置没有被允许
WARNING: Access control is not enabled for the database.

#解决方式:开启安全认证
[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf 
security:
  authorization: enabled

2.警告二

#以root用户运行了
WARNING: You are running this process as the root user, which is not recommended.

#解决方式:使用普通用户启动
1.先关闭mongodb
[root@redis01 ~]# mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
2.创建mongo用户
[root@redis01 ~]# useradd mongo
[root@redis01 ~]# echo ‘123456‘|passwd --stdin mongo
Changing password for user mongo.
passwd: all authentication tokens updated successfully.
3.授权目录
[root@redis01 ~]# chown -R mongo.mongo /usr/local/mongodb/
[root@redis01 ~]# chown -R mongo.mongo /server/mongo_27017/
4.重新启动
[root@redis01 ~]# su - mongo
Last login: Wed May 27 09:07:51 CST 2020 on pts/1
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf

3.警告三、四

#你使用的是透明大页,可能导致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‘

#解决方法:
执行 echo never > /sys/kernel/mm/transparent_hugepage/enabled
#         
执行 echo never > /sys/kernel/mm/transparent_hugepage/defrag

#配置之后重启
[root@redis01 ~]# su - mongo
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf

#这样设置是临时的,我们要把他加到 rc.local,在授个权
cat >> /etc/rc.local <<‘EOF‘
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF
chown mongo.mongo /etc/rc.local

4.警告五

#rlimits太低,MongoDB的软件进程被限制了,MongoDB希望自己是最少rlimits 32767.5
WARNING: soft rlimits too low. rlimits set to 7837 processes, 65535 files. Number of processes should be at least 32767.5 : 0.5 times number of files.

#解决方法:
[root@redis01 ~]# vim /etc/profile
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 65535
ulimit -m unlimited
ulimit -u 65535

[root@redis01 ~]# vim /etc/security/limits.d/20-nproc.conf
*          soft    nproc     65535
root       soft    nproc     unlimited

[root@redis01 ~]# source /etc/profile

五、基本操作

1.操作说明

CRUD操作是create(创建), read(读取), update(更新)和delete(删除) 文档。
MongoDB不支持SQL但是支持自己的丰富的查询语言。

在MongoDB中,存储在集合中的每个文档都需要一个唯一的 _id字段,作为主键。如果插入的文档省略了该_id字段,则MongoDB驱动程序将自动为该字段生成一个ObjectId_id。也用于通过更新操作插入的文档upsert: true.如果文档包含一个_id字段,该_id值在集合中必须是唯一的,以避免重复键错误。

在MongoDB中,插入操作针对单个集合。 MongoDB中的所有写操作都是在单个文档的级别上进行的

2.基本操作

参考网站

show databases/show dbs             #查看库列表
show tables/show collections        #查看所有的集合
use admin                           #切换库(没有的库也可以进行切换,没有数据是看不到)
db                                #查看当前库
show users                          #打印当前数据库的用户列表

test:登录时默认存在的库
admin库:系统预留库,MongoDB系统管理库
local库:本地预留库,存储关键日志
config库:MongoDB配置信息库

数据库的启动与关闭

启动:
mongod --dbpath=/application/mongodb/data --logpath=/application/mongodb/log/mongodb.log --port=27017 --logappend --fork
关闭:
mongod --shutdown  --dbpath=/application/mongodb/data --logpath=/application/mongodb/log/mongodb.log --port=27017 --logappend --fork

切忌kill -9
数据库直接关闭,数据丢失,数据文件损失,修复数据库(成本高,有风险)

参数说明:

参数 参数说明
--dbpath 数据存放路径
--logpath 日志文件路径
--logappend 日志输出方式
--port 启用端口号
--fork 在后台运行
--auth 是否需要验证权限登录(用户名和密码)
--bind_ip 限制访问的ip
--shutdown 关闭数据库

数据库简单操作

[mongod@MongoDB ~]$ mongo
MongoDB shell version: 3.2.8
connecting to: test
>
#查看当前数据库版本
> db.version()
4.2.9-rc0
#切换数据库
> use test
switched to db test
#显示当前数据库
> db
test
> db.getName()
test
#查询所有数据库
> show dbs;
> show databases
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
#查看数据库当前状态
> db.stats()
{
	"ok" : 0,
	"errmsg" : "command dbStats requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized"
}
#查看当前数据库连接机器地址
> db.getMongo()
connection to 127.0.0.1:27017

#创建数据库:
当use的时候,系统就会自动创建一个数据库。
如果use之后没有创建任何集合。系统就会删除这个数据库。

#删除数据库:
如果没有选择任何数据库,会删除默认的test数据库
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }

集合

#创建集合
方法一:
> db.createCollection(‘a‘)
{ "ok" : 1 }
> show collections;
a
> db.getCollectionNames()
[ "a" ]

方法二:
当插入一个文档的时候,一个集合就会自动创建。
> db.c.insert({name:"syy"})
WriteResult({ "nInserted" : 1 })
> db.c.insert({id:1})
WriteResult({ "nInserted" : 1 })

查看当前数据库下的所有集合
> show collections;
a
c

查看集合中的所有内容
> db.c.find()
{ "_id" : ObjectId("5f3cc985b41c01521e1601fa"), "name" : "syy" }
{ "_id" : ObjectId("5f3cc999b41c01521e1601fb"), "id" : 1 }

重命名集合
> db.c.renameCollection(‘cc‘)
{ "ok" : 1 }
> show collections
a
cc

删除集合
> show collections
a
cc
> db.cc.drop()
true
> show collections
a

3.插入数据

1)单条数据插入

db.test.insert({"name":"lhd","age":18,"sex":"男"})

db.test.insert({"name":"lhd","age":18,"sex":"男","address":"上海浦东新区"})

db.test.insertOne({"name":"lhd","age":18,"sex":"男","address":"上海浦东新区"})

2)多条数据插入

db.inventory.insertMany( [
    { "name": "lhd", "age": 18, "figure": { "h": 182, "w": 200 }, "size": "big" },
    { "name": "qiudao", "age": 88, "figure": { "h": 120, "w": 160 }, "size": "very bittle" },
    { "name": "zengdao", "age": 18, "figure": { "h": 180, "w": 160 }, "size": "nomel" },
 ]);
 
在集合中插入1w条数据
for(i=0;i<10000;i++){ db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()}); }
WriteResult({ "nInserted" : 1 })

4.查询数据

查看集合存储信息

> db.log.stats()          # 查看数据状态
{
	"ns" : "test.log",
	"size" : 800000,
	"count" : 10000,
	"avgObjSize" : 80,
	"storageSize" : 131072,
	"capped" : false,
	"wiredTiger" : {
		"metadata" : {
			"formatVersion" : 1
		},
> db.log.dataSize()       # 集合中数据的原始大小	
800000
> db.log.totalIndexSize() # 集合中索引数据的原始大小
110592
> db.log.totalSize()      # 集合中索引+数据压缩存储之后的大小
241664
> db.log.storageSize()    # 集合中数据压缩存储的大小
131072

1)查询所有数据

> db.test.find()
{ "_id" : ObjectId("5ecdcdac13a4155a65ecb332"), "name" : "lhd", "age" : 18, "sex" : "男" }
{ "_id" : ObjectId("5ecdcdc413a4155a65ecb333"), "name" : "lhd", "age" : 18, "sex" : "男", "address" : "上海浦东新区" }
{ "_id" : ObjectId("5ecdcdd213a4155a65ecb334"), "name" : "lhd", "age" : 18, "sex" : "男" }
{ "_id" : ObjectId("5ecdcdd813a4155a65ecb335"), "name" : "lhd", "age" : 18, "sex" : "男", "address" : "上海浦东新区" }

如果集合中数据很多,默认每页显示20条记录,当显示不下的的情况下,可以用it迭代命令查询下一页数据。
DBQuery.shellBatchSize=50;       # 每页显示50条记录
app> db.log.findOne()            # 查看第1条记录
app> db.log.count()              # 查询总的记录数
app> db.log.find({uid:1000});    # 查询UUID为1000的数据

db.log.distinct("name")      #  查询去掉当前集合中某列的重复数据

2)查询单条数据

> db.test.findOne()
{
    "_id" : ObjectId("5ecdcdac13a4155a65ecb332"),
    "name" : "lhd",
    "age" : 18,
    "sex" : "男"
}

> db.log.find({uid:1000}).pretty()
{
	"_id" : ObjectId("5f3cce8db41c01521e162cf4"),
	"uid" : 1000,
	"name" : "mongodb",
	"age" : 6,
	"date" : ISODate("2020-08-19T07:02:37.941Z")
}

3)按条件查询

#如果查询条件为数字,不需要加引号,字符需要加引号
> db.test.findOne({"name" : "lhd"})
{
    "_id" : ObjectId("5ecdcdac13a4155a65ecb332"),
    "name" : "lhd",
    "age" : 18,
    "sex" : "男"
}

4)查询多条件

#多个条件,并且
> db.inventory.find({"figure.h":120,"size":"very bittle"})

> db.inventory.find(
    {
        "figure.h":120,
        "size":"very bittle"
    }
)

#表示多条件或者
> db.inventory.find({$or:[{"figure.h":120},{"size":"big"}]})

> db.inventory.find(
    {
        $or [
            {"figure.h":120},
            {"size":"big"}
        ]
    }
)

#查看第一个
> db.test.findOne()
{
	"_id" : ObjectId("5f3c8c530a5f03e87646db23"),
	"name" : "lhd",
	"age" : 18,
	"sex" : "男",
	"address" : "上海浦东新区"

5)条件加范围的查询

# $or或者,$lt小于,$gt大于
> db.inventory.find({$or:[{"figure.h":{$lt:130}},{"size":"big"}]})

> db.inventory.find(
    {
        $or [
            {"figure.h":{$lt:130}},
            {"size":"big"}
        ]
    }
)

5.修改数据

1)修改单个数据

> db.inventory.updateOne({"name":"qiudao"},{$set:{"figure.h":130}})

> db.inventory.updateOne(
    #条件
    {"name":"qiudao"},
    {
        $set:
            #修改的值
            {"figure.h":130}
    }
)

6.索引

1)查看执行计划

> db.inventory.find().explain()
{   #查询计划
    "queryPlanner" : {
        #计划版本
        "plannerVersion" : 1,
        #被查询的库和集合
        "namespace" : "test2.inventory",
        #查询索引设置
        "indexFilterSet" : false,
        #查询条件
        "parsedQuery" : {
            
        },
        #成功的执行计划
        "winningPlan" : {
            #全表扫描
            "stage" : "COLLSCAN",
            #查询方向
            "direction" : "forward"
        },
        #拒绝的计划
        "rejectedPlans" : [ ]
    },
    #服务器信息
    "serverInfo" : {
        "host" : "redis01",
        "port" : 27017,
        "version" : "3.6.13",
        "gitVersion" : "db3c76679b7a3d9b443a0e1b3e45ed02b88c539f"
    },
    "ok" : 1
}

COLLSCAN 全表扫描
IXSCAN 索引扫描

2)创建索引

> db.inventory.createIndex({"age":1},{background:true})
{
    "createdCollectionAutomatically" : true,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

#添加索引
createIndex({索引的名称:1}) :1表示正序,-1表示倒序

#创建方式
1.前台方式 
缺省情况下,当为一个集合创建索引时,这个操作将阻塞其他的所有操作。即该集合上的无法正常读写,直到索引创建完毕
任意基于所有数据库申请读或写锁都将等待直到前台完成索引创建操作
 
2.后台方式
将索引创建置于到后台,适用于那些需要长时间创建索引的情形
这样子在创建索引期间,MongoDB依旧可以正常的为提供读写操作服务
等同于关系型数据库在创建索引的时候指定online,而MongoDB则是指定background
其目的都是相同的,即在索引创建期间,尽可能的以一种占用较少的资源占用方式来实现,同时又可以提供读写服务
后台创建方式的代价:索引创建时间变长

#规范
1.如果要查询的内容都是最近的,那建立索引就用倒序,如果要通盘查询那就用正序。
2.比如说一个数据集合查询占的比较多就用索引,如果查询少而是插入数据比较多就不用建立索引。因为:当没有索引的时候,插入数据的时候MongoDB会在内存中分配出一块空间,用来存放数据。当有索引的时候在插入数据之后还会给自动添加一个索引,浪费了时间。
3.不是所有数据都要建立索引,要在恰当并且需要的地方建立才是最好的。
4.大数量的排序工作时可以考虑创建索引。

3)查看索引

> db.inventory.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test2.test2"
    },
    {
        "v" : 2,
        "key" : {
            "age" : 1
        },
        "name" : "name_1",
        "ns" : "test2.test2",
        "background" : true
    }
]

4)再次查看执行计划

> db.inventory.find({"age":{$lt:40}}).explain()
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                #走索引了
                "stage" : "IXSCAN",

6.删除

1)删除单条数据

> db.inventory.deleteOne({"name":"lhd"})
{ "acknowledged" : true, "deletedCount" : 1 }

2)删除多个数据

> db.inventory.deleteMany({"name":"lhd"})

> db.log.remove({})             #  删除集合中所有记录
WriteResult({ "nRemoved" : 10000 })

3)删除索引

> db.test.dropIndex({ age: 1 })
{
    "ok" : 0,
    "errmsg" : "ns not found",
    "code" : 26,
    "codeName" : "NamespaceNotFound"
}

4)删除集合

#先确认自己在哪个库
> db
test2

#确认集合
> show tables;
inventory
test

#删除集合
> db.inventory.drop()
true

5)删除库

#先确认自己在哪个库
> db
test2

#删除库
> db.dropDatabase()

六、mongo工具

mongo               #登录命令
mongodump           #备份导出,全备(数据是压缩过的)
mongorestore        #恢复数据
mongostat           #查看运行状态的
mongod              #启动命令
mongoexport         #备份,导出json格式
mongoimport         #恢复数据
mongos              #集群分片命令
mongotop            #查看运行状态

1.mongostat命令

#不加任何参数时,每秒访问一次
[mongo@redis01 ~]$ mongostat
insert query update delete getmore command dirty used flushes vsize   res qrw arw net_in net_out conn                time
    *0    *0     *0     *0       0     2|0  0.0% 0.0%       0  972M 56.0M 0|0 1|0   158b   60.9k    1 May 27 11:23:08.248

insert      #每秒插入数据的数量
query       #每秒查询操作的数量
update      #每秒更新数据的数量
delete      #每秒删除操作的数量
getmore     #每秒查询游标时的操作数
command     #每秒执行的命令数
dirty       #脏数据占缓存的多少
used        #使用中的缓存
flushes
            #在 wiredtiger引擎,表示轮询间隔
            #在MMapv1引擎,表示每秒写入磁盘次数
vsize       #虚拟内存使用量
res         #物理内存使用量
qrw         #客户端等待读数据的队列长度
arw         #客户端等待写入数据的队列长度
net_in      #网络进流量
net_out     #网络出流量
conn        #连接总数
time        #时间

#一般该命令搭配  mongotop 命令使用,可以显示每个集合的响应速度

七、用户授权认证

用户中权限的说明

权限 说明
Read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin 允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root 只在admin数据库中可用。超级账号,超级权限

1.授权命令

用户管理界面
要添加用户, 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() 更新用户数据。

#验证用户和密码,返回 1 即为成功
> db.auth("admin","root")
Error: Authentication failed.
0
> db.auth("admin","123")
1
#查看用户
> use admin
> db.getUser("admin")
#删除用户
> use test
> db.dropUser("test")
true
#修改用户密码
1.
> use admin
db.changeUserPassword("admin","123")
2.
> use admin
switched to db admin
> db.updateUser("syy",{pwd:"123"})

2.创建用户和角色

[mongo@db01 ~]$ mongo
> use admin
> db.createUser({user: "admin",pwd: "123456",roles:[ { role: "root", db:"admin"}]})
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}

#创建管理员角色用户的时候,必须到admin下创建。删除的时候也要到相应的库下操作。

3.查看用户

#1.
> db.getUsers()
[
    {
        "_id" : "test.admin",
        "userId" : UUID("b840b96c-3442-492e-a45f-6ca7dff907fd"),
        "user" : "admin",
        "db" : "test",
        "roles" : [
            {
                "role" : "root",
                "db" : "admin"
            }
        ]
    }
]

#2.
> use admin
> show tables
system.users
system.version
> db.system.users.find().pretty()
{
	"_id" : "admin.syy",
	"userId" : UUID("dbc40d94-5bd3-4316-9228-be44a6a8af78"),
	"user" : "syy",
	"db" : "admin",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 10000,
			"salt" : "GBrul3/8Z7JiNdCzZVIRlA==",
			"storedKey" : "tobRAcAsP3z1oqQnDhNuz/ls808=",
			"serverKey" : "L2ZRMNwpBwEy5MC/3T/Cy6c5NyA="
		},
		"SCRAM-SHA-256" : {
			"iterationCount" : 15000,
			"salt" : "lDrQAvBmZtKO7U23PZclDNdIIyyD2PtfixWGbg==",
			"storedKey" : "pjHn1k30bd9+s0v8Gi6PnqwP6bCs2z+hKlSB5Pu5kC0=",
			"serverKey" : "qaRo0eLdWVbVdlt0AHwii3Cxoni8eVkx+iMQwEu+qN8="
		}
	},
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
#3.
> show users
{
	"_id" : "admin.admin",
	"userId" : UUID("4166d884-605f-4ccf-8313-7a4aa8e9fe81"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}

4.配置开启认证

[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf 
security:
  authorization: enabled
  
#重启
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf

5.配置认证以后查操作不了

[root@db03 ~]# mongo
> show databases;
2020-05-27T11:41:06.186+0800 E QUERY    [thread1] Error: listDatabases failed:{
    "ok" : 0,
    "errmsg" : "there are no users authenticated",
    "code" : 13,
    "codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
shellHelper.show@src/mongo/shell/utils.js:860:19
shellHelper@src/mongo/shell/utils.js:750:15
@(shellhelp2):1:1

6.使用账号密码连接

[mongo@redis01 ~]$ mongo -uadmin -p --authenticationDatabase admin
MongoDB shell version v3.6.13
Enter password: 

> show databases;
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
test2   0.000GB

#用户在哪个数据库下创建的,最后加上什么库
#--authenticationDatabase可以省略

7.创建普通用户

#在数据库test下,创建多规则用户
> use test
> db.createUser(
  {
    user: "test",
    pwd: "123456",
    roles: [ { role: "readWrite", db: "write" },
             { role: "read", db: "read" } ]
  }
)

#一定要要先进入指定的库,再创建用户,创建的用户在指定的库才能看到
#role的规则有:read readwrite dbAdmin(某库下的root)

8.创建测试数据

use write
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})
db.write.insert({"name":"haoda","age":18,"ad":"上海浦东新区"})
db.write.insert({"name":"linda","age":18,"ad":"上海浦东新区"})
db.write.insert({"name":"linhao","age":18,"ad":"上海浦东新区","sex":"boy"})

use read
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})
db.read.insert({"name":"haoda","age":18,"ad":"上海浦东新区"})
db.read.insert({"name":"linda","age":18,"ad":"上海浦东新区"})
db.read.insert({"name":"linhao","age":18,"ad":"上海浦东新区","sex":"boy"})

9.验证

mongo -utest -p --authenticationDatabase test
use write
db.write.find()
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})

use read
db.read.find()
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦东新区"})
2020-08-19T16:16:50.504+0800 E  QUERY    [js] uncaught exception: Error: no object passed to insert! :

mongoDB初识01

原文:https://www.cnblogs.com/syy1757528181/p/13530364.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!