MongoDB安装 & 用户创建增删改查

一、MongoDB安装部署

0.安装依赖

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

1.上传或下载包

#下载地址:https://www.mongodb.com/download-center/community
[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.91
  
  
#配置详解
#日志相关
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.91

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/mongo.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,在授个权

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配置信息库

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" },
 ]);

4.查询数据

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" : "上海浦东新区" }

2)查询单条数据

# 也就是查询出test集合中最上面的一条数据
> db.test.findOne()
{
    "_id" : ObjectId("5ecdcdac13a4155a65ecb332"),
    "name" : "lhd",
    "age" : 18,
    "sex" : "男"
}

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"}
        ]
    }
)

5)条件加范围的查询

> 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}
    }
)

2)修改多条数据

> db.table.updateMany({name:"niulei"},{$set:{age:"18"}})
{ "acknowledged" : true, "matchedCount" : 4, "modifiedCount" : 3 }

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"})

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 命令使用,可以显示每个集合的响应速度

五、用户授权认证

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() 更新用户数据。

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"
                }
        ]
}


role: 权限
db: 拥有对那个库的操作权限

# mongodb与其他数据库不一样,mongo中在哪个库中创建的用户只有对那个库操作的权限,除非在role中特别说明权限。
#用户角色:
1.可以使用的数据库管理员角色如下:
dbAdmin——授予执行管理任务的特权
userAdmin——允许您在当前数据库上创建和修改用户和角色
dbOwner——此角色结合了以下内容:
    readWrite
    dbAdmin
    userAdmin

2.集群管理员角色
用于管理整个系统的管理数据库中的角色。
clusterMonitor——提供对监视工具的只读访问
clusterManager——用于管理和监视集群上的操作
hostManager——监视和管理服务器
clusterAdmin——结合了其他三个角色和dropDatabase操作

3.备份和恢复角色
这个角色属于管理数据库。
backup——提供备份数据所需的特权
restore——提供从备份中还原数据所需的特权

4.所有数据库角色
这些角色位于管理数据库上,并提供适用于所有数据库的特权。
readAnyDatabase——与“read”角色相同,但适用于所有数据库
readWriteAnyDatabase——与“readWrite”角色相同,但适用于所有数据库
userAdminAnyDatabase——与‘userAdmin’角色相同,但适用于所有数据库
dbAdminAnyDatabase——与“dbAdmin”角色相同,但适用于所有数据库

5.超级用户角色
以下角色不是直接的超级用户角色,但是能够为任何用户分配任何数据库上的任何特权,也包括他们自己。
userAdmin
dbOwner
userAdminAnyDatabase
root角色提供对所有资源的完全特权:
root

3.查看用户

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

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.配置认证以后查操作不了

> 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

7.创建普通用户

> use test
> db.createUser(
  {
    user: "test",
    pwd: "123456",
    roles: [ { role: "readWrite", db: "write" },
             { role: "read", db: "read" } ]
  }
)

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":"上海浦东新区"})

10.修改用户密码

#修改用户信息
db.updateUser("test",{pwd:"123"})

#修改密码
db.changeUserPassword("admin","123")
原文地址:https://www.cnblogs.com/tcy1/p/13529934.html