一、介绍

在介绍 MongoDB 之前,我先介绍一下业务开发的时候遇到的痛点,以便大家对它有一个更加清晰的认识!

最近在用数据库存储数据的时候发现这么一个坑,例如从消息队列中监听消息的时候,原来的做法是将监听的消息数据存储在数据库,以便好对异常消息数据进行追溯,消息内容使用text类型存储,起初因为数据内容很短,没啥毛病,但是当随着业务的扩展,收到的消息内容越来越长,最后发现数据库中的text字段类型无法很好的支持查询,于是在这个时候,就开始考虑采用更加合适的数据库来存储这种消息数据!

在经过一番讨论之后,对于这种 json 类型的消息数据的存储,大家一致认为采用 MongoDB 是最佳的选择!

据官方介绍,MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富、最像关系数据库的一款高性能的 NoSQL 数据库。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。

其中的文档类似于 JSON 对象。字段值可以包含其他文档、数组及文档数组,数据结构的支持非常灵活!

的确,在使用的过程当中,正如所介绍的,数据的存储和查询,性能极快,而且很好的满足我们的需求!

话不多说,下面我们就一起来了解一下,这款数据库应该如何使用!

二、环境配置

在学习它之前,我们需要先搭建好环境,MongoDB 的安装也非常简单!

2.1、Windows 平台

如果你是 Windows 平台,MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制,安装基本是傻瓜式的操作,登录 MongoDB 官网并且下载安装包,然后一步一步的操作即可!

2.2、Linux 平台

生产环境基本都是 Linux 平台,为了和生产保持一致,小编采用的服务器是CentOS7,安装过程也比较简单!

  • 创建资源文件
sudo vim /etc/yum.repos.d/mongodb-org-4.0.repo
  • 编辑内容如下
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
  • 运行以下命令安装 mongodb
sudo yum install -y mongodb-org
  • 安装完成之后,配置mongod.conf允许远程连接
#编辑mongod.conf
vim /etc/mongod.conf
#将net:bindIp: 127.0.0.1 改为 0.0.0.0
net:
bindIp:0.0.0.0
  • 最后启动服务
#开启服务
systemctl start mongod #其他服务
#关闭服务
systemctl stop mongod #重启服务
systemctl restart mongod #开机自启
systemctl enable mongod

至此,环境配置已经完成!

三、数据库操作

MongoDB 的数据操作,是开发人员接触最频繁的部分,第一次使用的时候,你会发现它和我们传统使用的 sql 脚本命令完全不同,但是又类似,下面我们就一起来深入的了解下!

3.1、进入 MongoDB

进入 MongoDB 服务很简单,输入如下命令即可进入!

mongo

例如,在CentOS里面输入命令之后,进入的服务界面如下:

3.2、创建数据库

MongoDB 创建数据库的语法格式如下:

use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切换到指定数据库

输入如下命令,可以查询数据库列表

#查询数据库列表
show dbs #命令输出结果:
admin
config
local

可以看到,当前 MongoDB 有三个数据库!

输入如下命令,可以切换到admin数据库

use admin

输入db命令,还可以查询当前数据库

db

3.3、创建用户

默认的情况下,是没有用户的,也无法操作数据库,因此我们需要创建一个用户,同时给他分配权限!

3.3.1、创建一个管理员用户

创建一个用户、密码都是admin的用户,同时给这个用户分配userAdminAnyDatabase角色,指定的数据库为admin

#创建一个admin用户
db.createUser(
{
  user: "admin",
  pwd: "admin",
  roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})

其中字段含义如下:

  • user:用户的名字;
  • pwd:用户的密码;
  • roles:指定用户的角色,可以用一个空数组给新用户设定空角色。
  • roles 中的 role:指定角色。
  • roles 中的 db:指定的数据库,例如上面中的角色userAdminAnyDatabase,只在 admin 数据库中可用。

角色在 MongoDB 中,代表着某个用户是否有权限访问数据库或者操作数据库,理解这点非常重要!

MongoDB 角色定义如下:

角色类型 名称 描述
admin数据库角色 readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
admin数据库角色 readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
admin数据库角色 userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
admin数据库角色 dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
admin数据库角色 clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
admin数据库角色 root 只在admin数据库中可用,超级账号,超级权限
数据库管理角色 dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
数据库管理角色 userAdmin 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户
数据库用户角色 read 允许用户读取指定数据库
数据库用户角色 readWrite 允许用户读写指定数据库
3.3.2、创建一个不受访问限制的超级用户

如果你想创建一个不受访问限制的超级用户,赋予root角色即可!

#创建超级用户
db.createUser(
{
user:"root",
pwd:"root",
roles:["root"]
}
)
3.3.3、创建一个业务数据库普通用户

如果你想创建一个业务数据库普通用户,例如只能访问test_db数据库,并且只负责数据的増查改删。

# 创建或者切换数据库到test_db
use test_db # 创建一个test用户,并且只能访问test_db,对表只有读写权限
db.createUser(
{
  user: "test",
  pwd: "test",
  roles: [ { role: "readWrite", db: "test_db" } ]
})
3.3.4、验证用户是否可以正常登录

对于刚刚创建的用户,我们怎么验证它是否能正常登录呢?命令也很简单!

db.auth("test","test")

如果返回是1表示鉴权正常!

3.3.5、查询当前数据库用户信息

查询创建的用户,命令也很简单!

# 查看创建的用户
show users
3.3.6、修改用户密码

有些时候,我们会忘记密码,可通过如下方式进行修改!

#修改用户密码
db.changeUserPassword("username", "xxxxx")
3.3.7、删除用户

如果某个用户需要停用,可通过如下方式进行删除

#切换指定数据库
use test_db #删除用户
db.dropUser('test')
3.3.8、删除数据库

如果某个数据库需要停用,可通过如下方式进行删除(只有超级管理员有权限删除)

#切换指定数据库
use test_db #删除数据库
db.dropDatabase()

3.4、创建集合

MongoDB 并无这个概念,而对应的定义叫:集合,我们在关系型数据库中看到的表数据,在 MongoDB 中被定义为:文档,MongoDB 也被很多人成为文档数据库

在关系型数据库中,表数据是一行一行的存储,但是在 MongoDB 中,可能不是这样,如果你存储的 json 非常复杂,嵌套很深,那么在 MongoDB 中存储的行数,可能非常深,存储的时候类似我们在页面看到的父子表结构!

3.4.1、创建一个集合

MongoDB 中使用 createCollection() 方法来创建集合。

语法格式:

db.createCollection(name, options)

参数说明:

  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项

例如,在 test_db 数据库中创建 tb_user 集合:

# 切换到test_db数据库
use test_db # 创建 tb_user 集合
db.createCollection("tb_user") #输出结果
{ "ok" : 1 }

如果要查看已有的集合,可以使用show collections命令!

show collections

下面是带有几个关键参数的createCollection()的用法,下面命令表示:创建固定集合tb_user,整个集合空间大小6142800KB, 文档最大个数为10000

db.createCollection("tb_user", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )

在 MongoDB 中,很多时候不需要手动创建集合。当你插入一个文档时,MongoDB 会自动创建集合!

# 向集合tb_user 插入一条文档数据
db.tb_user.insert({"name" : "张三"}) #查询集合
show collections # 输出结果
tb_user
3.4.2、删除一个集合

MongoDB 中使用 drop() 方法来删除集合。

语法格式:

db.collection.drop()

例如,删除在 test_db 数据库中 tb_user 集合:

# 切换到test_db数据库
use test_db # 创建 tb_user 集合
db.tb_user.drop() #输出结果
true

3.4、创建文档

创建文档,类似我们在关系型数据库中,将数据插入到数据库,操作也很简单!

3.4.1、插入文档

MongoDB 使用 insert()save() 方法向集合中插入文档。

语法如下:

db.COLLECTION_NAME.insert(document)

db.COLLECTION_NAME.save(document)
  • save():如果_id主键存在则更新数据,如果不存在就插入数据。
  • insert():若插入的数据主键已经存在,则会抛异常,提示主键重复,不保存当前数据。

例如,在test_db数据库的tb_user集合中,插入一条数据

db.tb_user.insert(
{
name:"张三",
age:18,
gender:"男",
tags: ['宅男', '技术控', '脱发严重']
})

如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

查看已插入文档,命令如下:

#查询tb_user集合中的数据
db.tb_user.find() # 输出结果
{ "_id" : ObjectId("6022310f6b5e964b0a5916e6"), "name" : "张三", "age" : 18, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }

当然,你还可以通过save()命令进行插入,如果不指定_id字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

例如,将张三年龄更新到30岁!

db.tb_user.save(
{
_id: ObjectId("6022310f6b5e964b0a5916e6"),
name:"张三",
age:30,
gender:"男",
tags: ['宅男', '技术控', '脱发严重']
})

查看文档

db.tb_user.find()

# 输出结果
{ "_id" : ObjectId("6022310f6b5e964b0a5916e6"), "name" : "张三", "age" : 30, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }
3.4.2、更新文档

MongoDB 提供了 update()save() 方法来更新集合中的文档。

语法格式如下:

db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。

例如,将张三年龄更新到22岁!

db.tb_user.update({'name':'张三'},{$set:{'age':22}})

查询已更新的数据

db.tb_user.find()

# 输出结果
{ "_id" : ObjectId("602235216b5e964b0a5916e8"), "name" : "张三", "age" : 22, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置multi参数为true

db.tb_user.update({'name':'张三'},{$set:{'age':22}},{multi:true})
3.4.3、删除文档

MongoDB 中的remove()函数是用来移除集合中的数据

语法格式如下:

db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

例如,删除姓名为张三的用户

db.tb_user.remove({'name':'张三'})

查询数据是否被删除

db.col.find()

#结果为空
3.4.4、查询文档

MongoDB 查询文档使用 find() 方法。

语法格式如下:

db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件
  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

db.col.find().pretty()

首先我们插入几条数据,插入结果如下:

例如,查询一个性别为的用户信息

#单个条件查询,类似 sql语句中的 gender = '男'
db.tb_user.find({"gender":"男"})

查询一个性别为,姓名为张三的用户

#多条件查询,类似 sql语句中的 gender = '男' and name = '李四'
db.tb_user.find({"gender":"男","name":"李四"})

查询一个性别为 或者 姓名为张三的用户

#多条件查询,类似 sql语句中的 gender = '男' or name = '李四'
db.tb_user.find({$or:[{"gender":"男"},{"name": "李四"}]})

查询一个性别为 或者 姓名为张三,同时年龄大于30的用户

#多条件查询,类似 sql语句中的 age > 30 and ( gender = '男' or name = '李四')
db.tb_user.find({"age": {$gt:30}, $or:[{"gender":"男"},{"name": "李四"}]})
3.4.5、分页查询文档

如果需要分页查询集合数据,可以使用limit()skip()函数,其中limit()表示读几条数据,skip()表示从第几条数据开始。

#从集合中的第三行数据开始,读2条数据返回
db.tb_user.find({}).limit(2).skip(3)
3.4.6、文档排序

和关系型数据库一样,MongoDB 可以使用sort()方法进行排序,通过参数指定排序的字段,并使用 1-1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

例如,查询tb_user文档,按照age进行升序排序!

db.tb_user.find({}).sort({"age":1})

3.5、创建索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

3.5.1、创建索引

MongoDB 使用 createIndex() 方法来创建索引,语法格式如下:

db.collection.createIndex(keys, options)

语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可!

例如,给tb_user文档中的age创建一个索引!

db.tb_user.createIndex({"age":1})

创建索引是一个比较耗时的动作,我们还可以通过参数配置,在后台创建索引。

db.tb_user.createIndex({"age":1}, {background: true})

通过在创建索引时加background:true的选项,让创建工作在后台执行!

3.5.2、查看索引

MongoDB 提供了getIndexes()方法,可以进行查看索引。

例如,查询tb_user集合中的索引

db.tb_user.getIndexes()
3.5.3、删除索引

不在需要的索引,我们可以将其删除。删除索引时,可以删除集合中的某一索引,可以删除全部索引。

语法格式:

db.COLLECTION_NAME.dropIndex("INDEX-NAME")

例如,删除集合tb_user集合中的age索引:

#查询索引
db.tb_user.getIndexes() #输出结果
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test_db.tb_user"
},
{
"v" : 2,
"key" : {
"age" : 1
},
"name" : "age_1",
"ns" : "test_db.tb_user"
}
]

删除对应的age_1索引!

db.tb_user.dropIndex("age_1")

四、客户端

对于任何一款数据库,如果没有可视化界面操作,在开发的时候,可以说极其不方便,下面推荐一款小编经常使用的一款客户端。

  • Robo 3T(免费、轻量级) ,可以访问官网获取

其中小编采用的是第二款,整体的体验比Robo 3T要一点,两者功能都比较齐全!

在使用的时候,可以根据个人喜爱进行选择!

五、重要的一步

网上发现很多 mongodb 被黑,使大家将目光投向了mongodb 的权限控制。

其实 mongodb 本身有一套完备的 RBAC 权限控制体系,这次被黑基本都是没有遵照 mongodb 的生产环境部署手册部署的结果。

我们平时玩一玩 mongodb 习惯了不设置用户名密码,当我们的数据库放到公网时,由于我们也没有设置用户名密码,任何人都可以随便访问,而且由于我们没有开启授权访问,使得任何登录到 mongodb 服务器的用户都拥有最高权限!

一些居心不良的人发现,就可以把我们的数据拷走,删除我们的数据库,从而勒索赎金!

再次提醒各位同学,别学会所有的技能,大门还一直开着,还抱怨我方防御塔怎么一直被摧毁!

以上文CentOS7安装为例,修改/etc/mongod.conf,在security部分添加如下配置,开启授权访问!

security:
authorization: enabled

修改完成之后,重启 mongodb 服务

#重启服务
systemctl restart mongod

六、小结

本文主要围绕 MongoDB 的使用,从环境配置、数据库使用,再到客户端工具选用,做了简单的介绍,可能有的地方总结的不到位,欢迎各位网友批评指出!

在下篇文章中,我们会详细的介绍SpringBootMongoDB的整合实践!

七、参考

1、MongoDB 官方文档

2、菜鸟教程 - mongodb

MongoDB,入门看这一篇足矣!的更多相关文章

  1. Spring入门看这一篇就够了

    前言 前面已经学习了Struts2和Hibernate框架了.接下来学习的是Spring框架...本博文主要是引入Spring框架... Spring介绍 Spring诞生: 创建Spring的目的就 ...

  2. Mybatis入门看这一篇就够了

    什么是MyBatis MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...

  3. Git入门看这一篇就够了! (转)

    Git 的三种状态 Git 有三种状态,你的文件可能处于其中之一: 已提交(committed):数据已经安全的保存在本地数据库中. 已修改(modified):已修改表示修改了文件,但还没保存到数据 ...

  4. MongoDB入门系列之科普篇

    ​ 目录 背景 对比 MongoDB的数据存储格式 背景 最近公司扩展了很多国外客户,那么一个很严重的问题就是翻译,对于国外客户来说,肯定看不懂中文,那就要项目中提供切换各自国家语言的功能. 由于每个 ...

  5. 真的,kafka 入门看这一篇准没错!

    什么是 Kafka Kafka 是一个分布式流式平台,它有三个关键能力 订阅发布记录流,它类似于企业中的消息队列 或 企业消息传递系统 以容错的方式存储记录流 实时记录流 Kafka 的应用 作为消息 ...

  6. JSON入门看这一篇就够了

    什么是JSON JSON:JavaScript Object Notation [JavaScript 对象表示法] JSON 是存储和交换文本信息的语法.类似 XML. JSON采用完全独立于任何程 ...

  7. 史上最全IO流详解,看着一篇足矣

    一:要了解IO,首先了解File类 File类里面的部分常量,方法 No. 方法或常量 类型 描述 1 public static final String pathSeparator 常量 表示路径 ...

  8. Spring Boot 配置文件中的花样,看这一篇足矣!

    在快速入门一节中,我们轻松的实现了一个简单的RESTful API应用,体验了一下Spring Boot给我们带来的诸多优点,我们用非常少的代码量就成功的实现了一个Web应用,这是传统的Spring应 ...

  9. zookeeper实现分布式锁总结,看这一篇足矣(设计模式应用实战)

    分布式锁纵观网络各种各样的帖子层出不穷,笔者查阅很多资料发现一个问题,有些文章只写原理并没有具体实现,有些文章虽然写了实现但是并不全面 借这个周末给大家做一个总结,代码拿来就可以用并且每一种实现都经过 ...

随机推荐

  1. ShardingSphere-proxy-5.0.0部署之分表实现(一)

    一.说明 环境准备:JDK8+     mysql 5.x 官网:https://shardingsphere.apache.org/ 下载地址:https://archive.apache.org/ ...

  2. CVPR2022 | A ConvNet for the 2020s & 如何设计神经网络总结

    前言 本文深入探讨了如何设计神经网络.如何使得训练神经网络具有更加优异的效果,以及思考网络设计的物理意义. 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟踪.经典论文解读.CV招聘 ...

  3. docker 操作 记录

    docker ps  #查看当前docker容器 docker exec -it  容器名称 sh  进入docker容器 docker stop 停止docker容器

  4. springboot整合ueditor实现图片上传和文件上传功能

    springboot整合ueditor实现图片上传和文件上传功能 写在前面: 在阅读本篇之前,请先按照我的这篇随笔完成对ueditor的前期配置工作: springboot+layui 整合百度富文本 ...

  5. JS:null

    null:它表示一个变量是空的或未知的. 看例子! var a = null; var b = 1; var c = "a"; var d; var e = "" ...

  6. 适配抖音!三角面转换和3d模型体量减小,轻量化一键即可完成!

    抖音3d特效,可谓是越来越火爆了,这个有着迪士尼画风的3D大眼,就刷屏了国内外用户的首页! 有人好奇这些特效究竟是怎么制作的?其实就是把3D模型调整适配到头部模型上,调整位置或者大小就可以制作出一个简 ...

  7. [WUSTCTF2020]朴实无华-1

    1.打开连接只有如下界面:    2.用bp抓包分析包内数据,未发现有用的信息:    3.进行目录扫描,获得robots.txt文件并进行访问:       4.访问/fAke_f1agggg.ph ...

  8. c# sqlsugar,hisql,freesql orm框架全方位性能测试对比 sqlserver 性能测试

    在2022年1月份本人做过一次sqlsugar,hisql,freesql三个框架的性能测试,上次主要是测的sqlserver下的常规插入(非bulkcopy的方式数据插入),hisql与目前比较流行 ...

  9. SAP Grid control( ALV Grid 列表 自定义 按钮)

    ALV 列表和按钮 效果 源代码 PROGRAM bcalvc_tb_menu_with_def_but. *&&&&&&&&& ...

  10. idea java 打包的方法

    方法1: 在pom.xml 里面加上maven打包的配置 <plugin> <groupId>org.springframework.cloud</groupId> ...