第二部分:关键技术领域的开源数据库实践【开源NoSQL数据库保姆级教程之Mongodb数据库】

NOSQL教程

NOSQL是什么

SQL 就是 Structor Query Language 结构化查询语言。

典型的关系型数据库最大的优点就是主从查找。缺点,就是限制字段4096,表的字段是不能自由更改的,不能某一个条目有一些字段,另外的条目的没有。

NoSQL(NoSQL = Not Only SQL )

意即"不仅仅是SQL"。在现代的计算系统上每天网络上都会产生庞大的数据量。这些数据有很大一部分是由关系数据库管理系统(RDBMS)来处理。 1970年 E.F.Codd's提出的关系模型的论文 "A relational model of data for large shared data banks",这使得数据建模和应用程序编程更加简单。

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

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

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

数据存储量大

  • mysql 1000万以内,数据库性能可以,上亿条则数据库性能有降低,进行mysql优化,当然和服务器性能有关系
  • oracle:几亿-几十亿,数据库性能有保障,商业付费高
  • mongodb: 单标存储的数据可以是 PB 级

B -> KB -> M -> G -> T -> PB -> EB -> ZB

说明:

1EB:相当于6700多万部iPhone手机的数据容量)的数据被储存在云端

1ZB 数据就相当于 500 万亿张自拍照、2.5 万亿首 MP3 歌曲。我国建成全球规模最大网络基础设施:6.6ZB

NOSQL四大家族

NoSQL中的四大家族主要是:列存储、键值、图像存储、文档存储,其类型产品主要有以下这些。

img

NOSQL的优势

NoSQL的优点/缺点

优点:

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

缺点:

  • - 没有标准化
  • - 有限的查询功能(到目前为止)
  • - 最终一致是不直观的程序

NOSQL与RDBMS对比

RDBMS vs NoSQL

img

MongoDB简介

MongoDB,Redis 是NO-SQL的杰出代表。是大数据,人工智能、分布式应用、高速缓存应用场景必备技能。

MongoDB是什么

img

 MongoDB并非芒果的意思,而是源于 Humongous(巨大)一词。中文叫盲狗*db*

MongoDB是面向文档的数据库,不是关系型数据库。它将原来*‘行’(row)的概念换成了更加灵活的‘文档’(document)模型*。面向文档的方式可以将文档和数组内嵌进来,所以用一条记录就可以表示很复杂的层次关系。 MongoDB没有模式,文档的键不会事先定义也不会固定不变。**

*Mongodb主要由文档(Document)、集合(Collection)、数据库(Database)三部分组成。*

一个MongoDB实例,由多个数据库(Database)组成;一个数据库,由多个集合(Collection)组成;一个集合,又由多个文档组成。注意Mongodb单个文档大小上限为16MB,确保不会使用过多的内存RAM或在传输过程中占用过多的带宽。为了存储更大的文档,Mongodb提供了GridFS。

img

作为开始,我们需要了解6个简单的概念:

  1. MongoDB有着与您熟知的‘数据库’(database,对于Oracle就是‘schema’)一样的概念。在一个MongoDB的实例中您有若干个数据库或者一个也没有,不过这里的每一个数据库都是高层次的容器,用来储存其他的所有数据。
  2. 一个数据库可以有若干‘集合’(collection),或者一个也没有。集合和传统概念中的‘表’有着足够多的共同点,所以您大可认为这两者是一样的东西。
  3. 集合由若干‘文档’(document)组成,也可以为空。类似的,可以认为这里的文档就是‘行’。
  4. 文档又由一个或者更多个‘域’(field)组成,您猜的没错,域就像是‘列’。
  5. ‘索引’(index)在MongoDB中的意义就如同索引在RDBMS中一样。
  6. ‘游标’(cursor)和以上5个概念不同,它很重要但是却常常被忽略,有鉴于此我认为应该进行专门讨论。关于游标有一点很重要,就是每当向MongoDB索要数据时,它总是返回一个游标。基于游标我们可以作诸如计数或是直接跳过之类的操作,而不需要真正去读数据。

小结一下,MongoDB由‘数据库’组成,数据库由‘集合’组成,集合由‘文档’组成。‘域’组成了文档,集合可以被‘索引’,从而提高了查找和排序的性能。最后,我们从MongoDB读取数据的时候是通过‘游标’进行的,除非需要,游标不会真正去作读的操作。

程序员注重对象,您的数据库也是。

MongoDB 是一个文档数据库,即在类似 JSON 的文档内存储数据。我们认为面对数据,这种方法非常自然,比传统的排/列模型更加直观和强大。

丰富的 JSON 文档

自然、高效的数据处理方法。

支持将数组和嵌套对象存储为值。

支持灵活、动态结构。

强大的查询语言

查询语言丰富和直观,支持通过任何字段进行筛选和排序,而不受其在文档内的嵌套方式影响。

支持聚合和其他现代使用案例,如基于地理的搜索、图搜索和文本搜索。

查询本身是 JSON 格式,因此很容易进行组合。无需串联字符串即可动态生成 SQL 查询。

MongoDB的特性

 MongoDB的3大技术特色如下所示:

img

除了上图所示的还支持:

二级索引、动态查询、全文搜索 、聚合框架、MapReduce、GridFS、地理位置索引、内存引擎 、地理分布等一系列的强大功能。

但是其也有些许的缺点,例如:

 多表关联: 仅仅支持Left Outer Join

 SQL 语句支持: 查询为主,部分支持

 多表原子事务: 不支持

 多文档原子事务:不支持

 16MB 文档大小限制,不支持中文排序 ,服务端 Javascript 性能欠佳

关系数据库与MongoDB的区别

存储方式对比


在传统的关系型数据库中,存储方式是以表的形式存放,而在MongoDB中,以文档的形式存在。

img

数据库中的对应关系,及存储形式的说明

img

MongoDB与SQL的结构对比详解

MongoDB数据存储格式

JSON****格式


  JSON 数据格式与语言无关,脱胎于 JavaScript,但目前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。

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

  JSON数据库语句可以容易被解析。

  Web 应用大量使用,NAME-VALUE 配对

img

BSON****格式

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

  二进制的JSON,JSON文档的二进制编码存储格式

  BSON有JSON没有的Date和BinData

  MongoDB中document以BSON形式存放

例如:

db.meeting.insert({meeting:“M1 June",Date:"2018-01-06"});

MongoDB的优势

📢 MongoDB是开源产品

  📢 On GitHub Url:https://github.com/mongodb

 📢 Licensed under the AGPL,有开源的社区版本

  📢 起源& 赞助by MongoDB公司,提供商业版licenses 许可

  这些优势造就了mongodb的丰富的功能:

  JSON 文档模型、动态的数据模式、二级索引强大、查询功能、自动分片、水平扩展、自动复制、高可用、文本搜索、企业级安全、聚合框架MapReduce、大文件存储GridFS

MongoDB应用场景

MongoDB适用场景


网站数据、缓存等大尺寸、低价值的数据

在高伸缩性的场景,用于对象及JSON数据的存储。

img

MongoDB 慎用场景


img

什么时候该MongDB


img

MongoDB安装和配置

https://github.com/yinjihuan/spring-data-mongodb

https://docs.whaleal.com/mongodb-manual-zh/#/01-introduction

安装前准备

非常简单,简单的令人发指。

1.芒果数据库,官网:https://www.mongodb.com/

选择合适版本

1.1 操作系统

1.2 Mongodb社区版或企业版
下载可以选择 zip 格式或者 msi 格式,msi 格式就是下一步、下一步安装。我们讲解 zip格式。

  • 解压缩这个文件夹,千万不要有中文路径
  • 解压之后找到你的 bin 文件夹,再次确认没有中文路径。
  • 将这个bin 文件夹路径设置为系统的环境变量
  • 在系统任何盘符下能够输入mongo命令不会报“mongo不是可以执行的命令”错误。说明你已经成功安装。

2.备用下载链接:http://dl.mongodb.org/dl/win32/x86_64

安装MongoDB

MSI安装

安装MongoDB数据库注意的事项:

  1. 一定要用管理员的身份运行
  2. 安装目录严禁使用中文目录
  3. 数据data目录更改到非系统盘,确保数据安全
  4. 默认27017端口,如果端口占用请更改netstat -a查看

1、双击msi安装包

img

img

取消MongoDB Compass的安装选项(不取消安装极慢),需要可自行安装;

直至100%完成

img

img

MongoDB默认提供admin、Local、config以及test四个数据库,具体如下:

  1. admin数据库,主要存储数据库账号的相关信息
  2. local数据库,可以用于存储限于本地单台服务器的任意集合,如oplog日志就存储在local数据库中,该数据库的数据不会被 复制到从结点上
  3. config数据库,用于存储分片集群中与分片相关的元数据信息
  4. test数据库,是Mongodb默认创建的一个测试库,当连接mongodb服务时,如果不指定连接的具体数据库,默认会连接到test数据库

ZIP包安装

zip解压安装

1. 文件配置

进入解压后的文件夹,新建data和log文件夹,并在log文件夹下,新建mongo.log空文件

新建mongo.conf文件与bin文件夹同级

mongo.conf写入以下内容

#数据库路径
dbpath=F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\data
#日志输出文件路径
logpath=F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\log\mongo.log
#错误日志采用追加模式
logappend=true
#启用日志文件
journal=true
#过滤一些无用的日志信息
quiet=true
#端口号,默认27017
port=27017

注:dbpath和logpath根据自己的具体路径进行修改

2. 安装

从bin文件夹下进入命令行执行

mongod --config "F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\mongo.conf"

注:引号内的路径换成刚刚配置文件的路径

正常情况下执行后窗口没有任何反应,其实是正常在生成data下默认的几个数据库文件,可以查看是否已经生成

img

3、注册/删除service服务

#注册服务
mongod --dbpath F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\data 
 --logpath F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\log\mongo.log 
--install --serviceName "mongodb"
#删除服务
./mongod --logpath "F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\log\mongo.log" 
--logappend --dbpath "F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\data\db" 
--directoryperdb --serviceName "mongodb" --serviceDisplayName "mongodb" --remove

4、查看服务及启动服务输入

net start mongodb

5、错误排查:

如果出现MongoDB服务无法启动,windows提示发生服务特定错误:100

解决办法:

img

然后重新启动mongodb服务即可

管理MongoDB

安装完成后,查询Mongodb系统服务mongoDB

方法一:自动启动mongodb数据库

img

Mongodb常用的命令

img


img

如果想关闭mongodb服务,可以使用mongo来实现

mongo 192.168.1.105:27017 use admin db.shutdownServer()

也可以直接使用mongod来实现

mongod --shutdown

启动和停止MongoDB服务


#启动MongoDB服务
net start MongoDB
#停止MongoDB服务
net stop MongoDB
#如果需要移除MongoDB服务,只需使用管理员权限运行cmd工具,并输入如下命令。
sc.exe delete MongoDB
或mongod --remove  MongoDB

img

连接MongoDB命令

例如:安装在C:\Program Files\MongoDB\Server\5.0\bin目录,先进入此目录,再执行如下命令


./mongo 127.0.0.1:27017

img

出现“>”号表示mogodb已正常启动

方法二:手动启动mongo数据库

1、启动数据库mongod(服务器端)

2、客户端连接 mongo

客户端工具

MongoDB客户端工具推荐:

1、NoSQL Manager for MongoDB Freeware

https://www.mongodbmanager.com/download

img

  1. 工具栏介绍
    • New MongoDB Connection:打开连接数据库页面
    • Shell:打开命令行操作页面
  2. 打开连接数据库页面

img

  • 命令行操作页面
    1. F5:执行全部命令
    2. F6:执行某一行命令,光标放在那一行上面
    3. F9:执行选择的命令

img

2、Navicat Premium全能数据库工具(强烈推荐)

Navicat Premium 是一套数据库开发工具,让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。它与 Amazon RDS、Amazon Aurora、Amazon Redshift、Microsoft Azure、Oracle Cloud、MongoDB Atlas、阿里云、腾讯云和华为云等云数据库兼容。你可以快速轻松地创建、管理和维护数据库。

默认情况下Navicat 不显示mongodb默认三个数据库,需要显示隐藏的项目

img

img

3、Robo 3T

https://robomongo.org/download

MongoDB的基本操作

数据类型

首先我们要先了解一下MongoDB中有什么样的数据类型:

Object ID :Documents 自生成的 _id

这是MongoDB生成的类似关系型DB表主键的唯一key,具体由24个字节组成:

0-8字节是时间戳,

9-14字节的机器标识符,表示MongoDB实例所在机器的不同;

15-18字节的进程id,表示相同机器的不同MongoDB进程。

19-24字节是计数器

注意如果插入文档时指定_id的值则MongoDB就不会赋值Object ID,但要注意_id的唯一性

获取_id可以执行ObjectId();

例如:


"_id" : ObjectId("5b151f8536409809ab2e6b26")

#"5b151f85" 代指的是时间戳time,这条数据的产生时间
#"364098" 代指某台机器的机器码machine,存储这条数据时的机器编号
#"09ab" 代指进程ID,PID多进程存储数据的时候,非常有用的
#"2e6b26" 代指计数器INC,这里要注意的是,计数器的数字可能会出现重复,不是唯一的
#以上四种标识符拼凑成世界上唯一的ObjectID
#只要是支持MongoDB的语言,都会有一个或多个方法,对ObjectID进行转换
#可以得到以上四种信息

#注意:这个类型是不可以被JSON序列化的

String: 字符串,必须是utf-8


Boolean:布尔值


true 或者false 这里首字母是小写的(这里有坑哦~在我们大Python中 True False 首字母大写)

Integer:整数


Int32 Int64 你们就知道有个Int就行了,一般我们用Int32

Double:浮点数


没有float类型,所有小数都是Double

Arrays:数组或者列表


多个值存储到一个键 (list哦,大Python中的List哦)

Object:如果你学过Python的话,那么这个概念特别好理解,就是Python中的字典,这个数据类型就是字典

Null:空数据类型 , 一个特殊的概念,None Null

Timestamp:时间戳


Date:存储当前日期或时间unix时间格式


我们一般不用这个Date类型,时间戳可以秒杀一切时间类型

数据库操作

MongoDB 中默认的数据库为 test,如果没有创建新的数据库,集合将存放在 test 数据库中。

【查看数据库】


使用show dbs来查看数据库

show dbs

【创建/切换】


使用use命令来切换/创建数据库,会发现创建的数据库并不在数据库的列表中, 要显示它,需要向数据库插入一些数据

use db_name

【显示当前数据库】


使用db命令来显示当前数据库,效果等同于 db.getName()

db

【删除数据库】


这将删除当前所选数据库。 如果没有选择任何数据库,那么它将删除默认的’test‘数据库

db.dropDatabase()

集合操作

一、创建集合

db.createCollection(name, options)

参数说明:

  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项
1 首先进入数据库   use   数据库名称
2 创建集合  db.creareCollection('集合名称')

创建集合有一些可选参数

size、capped都是在固定集合上使用的,我们一般将固定集合使用在日志上面,之前的日志文件难以维护,还要定期去处理。
有了固定集合当日志达到最大的时候他会覆盖最早的日志,这样减少了日志维护的资源;
db.createCollection("role",{capped:true,autoIndexId:true,size:6100000});
db.createCollection("student",{capped:true,autoIndexId:true,size:6100000});
db.createCollection("user");

这样就创建一个固定大小的集合,默认_id创建一个索引,在MongoDB里面每一行数据的_id都是唯一的。

max是该集合最大的文档数,也就是可以插入数据的上限;

二、删除集合

db.user.drop() 删除user集合

三、查看集合

db.getCollectionNames():获取当前 db 的所有集合,以数组形式显示

show collections:获取当前 db 的所有集合,以列表(换行)形式显示

show collections

img

四、集合的重命名

db.role.renameCollection('user')

img

文档操作

插入文档

 MongoDB的数据定义格式和JSON的数据定义格式是一样的,但是在MongoDB中我们把他称之为BSON(Binary JSON)是一种类json的一种二进制形式的存储格式。他的数据格式是非常丰富的,比如我们在MySQL中要联系两站表的关系我们会创建一个表,里面存放他们的关系。但是在MongoDB里面我们可以放在同一个文档里面,我们定义一个数组类型的属性,这个数组就可以存放他们之间的关系,只需要两个而不是三个。

要将数据插入到 MongoDB 集合中,需要使用 MongoDB 的 insert()或save()方法,还有insertOne()或insertMany()方法

 insert()命令的基本语法如下

db.COLLECTION_NAME.insert(document)

save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne()db.collection.replaceOne() 来代替。

insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。

在插入的文档中,如果不指定_id参数,那么 MongoDB 会为此文档分配一个唯一的ObjectId。_id为集合中的每个文档唯一的12个字节的十六进制数

_id,又称为ObjectId是一个12字节的BSON类型字符串。按照字节顺序依次代表:

db.course.insert({
    "name" : "数学",
    "type" : "major"
})

向课程表里插入一条数据

一次性插入多条数据db.collection.insertMany()

db.student.insert([
    {
        "stu_name" : "小明",
        "stu_number" : "2013001",
        "stu_sex" : "男",
        "course" : [
            ObjectId("5bb82bb3627eb5e25bead053"),
            ObjectId("5bb82c5f627eb5e25bead054"),
            ObjectId("5bb82c5f627eb5e25bead055"),
            ObjectId("5bb82c5f627eb5e25bead057"),
            ObjectId("5bb82c5f627eb5e25bead058")
        ],
    },
    {
        "stu_name" : "小红",
        "stu_number" : "2013002",
        "stu_sex" : "女",
        "course" : [
            ObjectId("5bb82bb3627eb5e25bead053"),
            ObjectId("5bb82c5f627eb5e25bead054"),
            ObjectId("5bb82c5f627eb5e25bead055"),
            ObjectId("5bb82c5f627eb5e25bead056"),
            ObjectId("5bb82c5f627eb5e25bead058")
        ],
    }
])

就像JSON一样。一次封装多个数据我们就用数组包裹起来就可以了,我们直接在学生表里面关联课程的信息,course就是我们学生所选的课程。

同样我们也可以定义一个变量

document1=( {
        "stu_name" : "小明",
        "stu_number" : "2013001",
        "stu_sex" : "男",
        "course" : [
            ObjectId("5bb82bb3627eb5e25bead053"),
            ObjectId("5bb82c5f627eb5e25bead054"),
            ObjectId("5bb82c5f627eb5e25bead055"),
            ObjectId("5bb82c5f627eb5e25bead057"),
            ObjectId("5bb82c5f627eb5e25bead058")
        ],
    },
    {
        "stu_name" : "小红",
        "stu_number" : "2013002",
        "stu_sex" : "女",
        "course" : [
            ObjectId("5bb82bb3627eb5e25bead053"),
            ObjectId("5bb82c5f627eb5e25bead054"),
            ObjectId("5bb82c5f627eb5e25bead055"),
            ObjectId("5bb82c5f627eb5e25bead056"),
            ObjectId("5bb82c5f627eb5e25bead058")
        ]
    });

再执行db.student.insert(document1);

还有一种插入的方法:

db.student.save(
    {
        "stu_name" : "小峰",
        "stu_number" : "2013009",
        "stu_sex" : "男",
        "course" : [
            ObjectId("5bb82bb3627eb5e25bead053"),
            ObjectId("5bb82c5f627eb5e25bead054"),
            ObjectId("5bb82c5f627eb5e25bead055"),
            ObjectId("5bb82c5f627eb5e25bead057"),
            ObjectId("5bb82c5f627eb5e25bead058")
        ],
    }
)

save也可以插入数据,如果save的数据在集合里面就直接替换更新,没有这个数据的存在就新增加一条。

shell的for循环批量插入文档:一次插入多条数据

1、先创建数组

2、将数据放在数组中

3、一次 insert 到集合中

更新文档

更新文档
db.student.update({
   查询的条件,
   更新的语句,
   附加的参数
})

附加的参数

img

db.student.insertMany([
    {
        "stu_name" : "小张",
        "stu_number" : "2013003",
    },
  {
        "stu_name" : "小张",
        "stu_number" : "2013002",
    },
    {
       "stu_name" : "小张三",
        "stu_number" : "2013004"
    }]
)

区分:update默认情况下是只修改一个文档,等同updateOne,如果需要修改多个可以使用multi:true属性

  1. db.collection.update(query, update);
db.student.update(
    {
        "stu_name" : "小张"
    },
    {
        $set : {"stu_name" : "小张二"}
    }
)
  1. db.collection.updateOne(query, update);
db.student.update(
    {
        "stu_name" : "小张"
    },
    {
        $set : {"stu_name" : "小张一"}
    }
)

修改多个文档

db.student.update(
    {
        "stu_name": "小张"
    },
    {
        $set: {
            "stu_name": "小张二"
        }
    },
    {
        multi: true
    }
)
  1. db.collection.updateMany(query, update);

$set : 用来指定一个键的值

$unset : 删除指定一个属性

$inc : 增加和减少(increase)

$push : 向数组尾部追加元素

$addToSet : 添加时避免重复, 例如:

Db.user.update({“_id”: “....”}, {‘$addToSet’: {‘emails’: ‘sky3hao@163.com’}}))

$addToSet 和 $each 组合起来,可以添加多个不同的值.

$pop : 从数组某一端删除元素

$pull : 基于条件来删除数组元素

test.update({'name':'foobar'},{$set:{'age':36}}) <==> update test set age=36 where name='foobar'

db.test.update({'name':'foobar'},{$inc:{'age':3}}) <==> update test set age=age+3 where name='foobar'

and条件,挨着写默认就是and

db.student.update(
    {
        "stu_name" : "小张",
        "stu_number" : "2013003",
    },
    {
        $set : {"stu_name" : "小张二"}
    }
)

or条件,要出现$or的关键字

db.student.update(
    {
         $or : [
            {"stu_name" : "小张二"},
            {"stu_number" : "2013003"}
        ],
    },
    {
        $set : {"stu_name" : "小张"}
    }
)

布尔运算符

1 $ne : 不等于 
2 $not : 不匹配结果 
3 $nor : 所有的条件都不匹配 
4 $exists : 判断元素是否存在
$inc
db.student.update(
    {
        "stu_number" : "2013001"
    },
    {
        $inc : {"mark" : 1}//自增1,为负数的时候就是减
    }
);

大于一个数据或小于一个数

db.student.update(
    {
        "stu_number" : {$gte:"2013001",$lte:"2013002"}
    },
    {
        $inc : {"mark" : 1}//自增1,为负数的时候就是减
    }
);

$exists

 db.student.find(
    {
        "stu_number" : {$exists:true}
    }
 );

返回这个字段存在的所有记录,当为false的时候结果就是相反;

删除操作

 db.student.remove({
   条件 
},属性)

img

db.student.remove(
 {
  "_id":ObjectId("5bb83384627eb5e25bead061")
 }
)

另外删除单个和多个文档:

#删除单个文档
db.student.deleteOne();
#删除多个文档
db.student.deleteMany();
#可以删除单个也可以多个如果设置true表示删除一个,否则多个
db.student.remove();
#删除集合中所有文档:清空
db.student.remove({});
#或使用性能最高的
db.student.drop();

查询操作

查询文档

掌握选择器(selector)****

MongoDB的查询选择器就像SQL代码中的where语句。因此您可以用它在集合中查找,统计,更新或是删除文档。选择器就是一个JSON对象,最简单的形式就是{},用来匹配所有的文档(null也可以)。如果我们需要找到所有雌性的独角兽(unicorn),我们可以用选择器{gender:'f'}来匹配。

要从MongoDB集合查询数据,需要使用MongoDB的find()方法,默认返回结果中的前20条文档,输入"it"显示接下来的20条文档。

 find()命令的基本语法如下:

db.COLLECTION_NAME.find(document)

find()方法将以非结构化的方式显示所有文档

比较运算符

查询的条件有:

等于equal;不等于not equal,小于less than,小于或等于equal or less than,大于greater than,大于或等于equal or greater than。

img

$not

db.student.find(
    {
        'stu_number' : {$not : {$ne : "2013002"}}
    }
).pretty()
这种情况下也会返回没有stu_number的字段,和$gt这些比较运算符是不同的,他们只会返回有的字段

范围运算符

$in,不在集合里面我们就用$nin

db.student.find(
    {
        'stu_number' : { $in : ["2013001","2013002"]}
    }
).pretty()
和Mysql的where in是一样的效果,他会查出2013001和002的数据

模糊查询:正则表达式

在mongoDB里面我们的模糊查询是按照正则表达式来进行匹配的

 db.student.find(
 {
     "stu_number":{$regex:/^2013/}
 }
 )

我们要查询一个数组里面一个字段的值,我们用点进行连接

{
    "userInfo" : {
        "name" : "张三",
        "age" : 28
    }
}
我们要查询name等于张三的信息

db.student.find({"userInfo.name":"张三"})

JavaScript查询

 db.student.find(
 {
     "$where" : "function () {return this.stu_number == '2013001'}"
 }
)

排序

1:升序

-1:降序

语法:

db.stu.find().sort({字段:1})

举例:

db.student.find().sort({"stu_number":-1}).pretty()

# 当为-1的时候是降序,1为升序

限制

db.student.find().sort({"stu_number":-1}).limit(5).pretty()
 限制显示5条数据

跳过

db.student.find().sort({"stu_number":-1}).limit(5).skip(2).pretty()

#跳过前两个并且显示5条数据

我们所看到的限制、跳过和Mysql的limit一样,限制就是第一个参数,跳过就是第二个参数偏移量。

查询返回特定的字段

db.student.find({},{'stu_number':0,}).sort({"stu_number":-1}).limit(5).skip(2).pretty()

当我们stu_number为0的时候,返回除了stu_number以外的数据,如果为1只返回stu_number一个字段的数据。

统计个数

db.stu.find(条件).count()
db.stu.count({条件})

消除重复

db.stu.distinct(去重字段, {条件})

聚合 aggregate

  1. 表达式
  2. $sum
  3. $avg
  4. $min
  5. $max
  6. $push: 数组
  7. $first
  8. $last
  9. $$ROOT: 将文档内容加入到结果集的数组中
#聚合管道操作
#性别分组并统计男女数
db.student.aggregate({
    $group: {
        _id:"$sex",
				num:{$sum:1}
    }
});
#多属性排序sort升序值1,降序为-1
db.student.aggregate([{$sort:{age:-1}},{$sort:{stu_name:-1}}]);
db.student.find().sort({age:-1},{stu_name:-1}).pretty();
#显示10条数据
db.student.find().sort({age:-1},{stu_name:-1}).limit(10).pretty();
db.student.find().sort({age:-1},{stu_name:-1}).limit(10).skip(2).pretty();
#求文档数
db.student.find().count();

综合CRUD练习

MongoDB综合练习{CRUD(Create、Read、Update、Delete)中的四个操作}

1.创建(进入)mytest数据库
2.向数据库的users集合插入一个username为张三的文档。
3.检查当前数据库和和当前集合有没创建成功。
4.查询users集合当中的文档。
5.统计当前数据库中users集合中的文档数量。
6.查询数据库users集合中username为张三的文档。
7.向数据库users集合中的username为张三的文档,添加一个address属性,属性值为深圳龙岗。
8.将username: "张三" 替换为 username:"李四"。
9.删除username为李四的文档的address属性。
10.向username为"李四"的文档中添加一个hobby:{cities:["上海","北京","广州"],movies:["卡通","惊悚","科幻"]}属性。(嵌套文档操作)
11.查询李四爱好movie中卡通的嵌套文档。
12.向李四中添加一个新的电影类型:爱情。
13.删除喜欢北京的用户。
14.清空users集合。
15.删除users集合(默认会把数据库也给删除了)。
16.新建一个myTest数据库,通过for循环向numbers集合中插入200条数据(数据即文档),并且统计当前数据数量是否够数。(tip:要点击文件刷新)
17.如果我们想向numbers集合插入20000条数据而不仅仅是200条数据呢,有没有性能高一点的法子?因为for遍历循环,意味着insert方法要执行3000次,性能肯定是差的了。
18.查询numbers集合中num为500的 文档。
19.查询numbers集合中num大于500的文档。
20.查询numbers集合中num小于30的文档。
21.查询numbers集合中num大于40小于50的文档。
22.查看numbers集合中的前10条数据。
23.查看numbers集合中的第11-20条的数据。

综合查询实战

使用Navicat Premium 15工具完成

1、将dept和emp集合json文件导入到数据库中

下载地址:

emp.json

dept.json

2、导入方法

img

img

img

特别注意下要确定好导的数据类型的选择,像一般工资属于数值型

img

然后默认下一步,直至最后完成!

独立完成以下练习

1.查询工资小于2000的员工

2.查询工资在1000-2000之间的员工

3.查询工资小于1000或大于2500的员工

4.查询财务部的所有员工

5.查询销售部的所有员工

6.查询所有mgr为7698的所有员工

7.为所有薪资低于1000的员工增加工资400元

MongoDB的系统管理

用户权限

角色-用户-数据库的安全管理方式

系统角色

root: 只在admin数据库的可用,超级账号/超级权限

Read: 允许用户读取指定数据库

readWrite: 允许用户读写指定数据库

创建管理员用户

创建超级管理员

use admin;
db.createUser({ user:'admin', pwd:'123', roles:[{role:'root',db:'admin'}] });

创建普通用户
use test;
db.createUser({ user:'test', pwd:'123', roles:[{role:'readWrite',db:'test'}] });

数据库备份和恢复

备份工具集下载和安装


要用到mongodump、mongorestore等工具时候发现原来下载的数据库文件缺失很多工具,需要单独下载
下载工具集:
https://www.mongodb.com/try/download/database-tools

下载完成后解压到mongodb/bin目录下即可

MongoDB数据备份


在Mongodb中我们使用mongodump命令来备份MongoDB数据。该命令可以导出所有数据到指定目录中。

mongodump命令可以通过参数指定导出的数据量级转存的服务器。

语法

mongodump命令脚本语法如下:

mongodump.exe -h dbhost -d dbname -o dbdirectory

全部备份:

mongodump.exe
  • -h:

    MongoDB 所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017

  • -d:

    需要备份的数据库实例,例如:test

  • -o:

    备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

实例

在本地使用 27017 启动你的mongod服务。打开命令提示符窗口,进入MongoDB安装目录的bin目录输入命令mongodump:

#数据库备份:找到mongodb数据库bin目录,例如:
在F:\database\MonogoDB\mongodb-win32-x86_64-windows-5.0.3\bin目录下
./mongodump.exe -h localhost:27017 -d db_student   -o  d:\

mongodump 命令可选参数列表如下所示:

语法 描述 实例
mongodump --host HOST_NAME --port PORT_NUMBER 该命令将备份所有MongoDB数据 mongodump --host localhost --port 27017
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY mongodump --dbpath /data/db/ --out /data/backup/
mongodump --collection COLLECTION --db DB_NAME 该命令将备份指定数据库的集合。 mongodump --collection mycol --db test

MongoDB数据恢复


mongodb使用 mongorestore 命令来恢复备份的数据。

语法

mongorestore命令脚本语法如下

>mongorestore -h <hostname><:port> -d dbname  --gzip <path>
  • --host <:port>, -h <:port>:
    MongoDB所在服务器地址,默认为: localhost:27017
  • --gzip是压缩包格式,导入文档时必须要加此参数

  • -db , -d :
    需要恢复的数据库实例
  • --drop:
    恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
  • <path>:mongorestore 最后的一个参数,设置备份数据实例所在位置,例如:c:/data/dump/test。
    你不能同时指定 和 --dir 选项,--dir也可以设置备份目录,整个例子:mongodump.exe -d test ./dump/test
  • --dir:
    指定备份的目录,例如 :./dump,备份目录内所有数据,所以-d不能使用,整个例子:mongodump.exe --dir ./dump
    你不能同时指定 和 --dir 选项。

例如:

./mongorestore.exe -h localhost -d db_student --gzip C:\Users\zhujw\Documents\db_student

Java操作MongoDB实战

任务描述

任务名称 Mongodb基本操作
任务要求 1、熟练掌握安装和配置MongoDB数据库 2、掌握数据库、集合和文档概念 3、学会如何创建数据库、删除数据库 4、学会集合的基本操作 5、学会文档的基本操作
任务内容 1、Java语言操作MongoDB数据库 2、获取MongoDB中的所有数据库 3、查看指定数据库(即数据库articledb)中的所有集合 4、创建集合 5、删除集合 6、查看文档 7、插入一个文档 8、更新文档 9、删除文档
提交内容 实践操作

任务准备

任务准备:

1、安装和配置好Mongdb数据库

2、熟练Mongodb基本操作

3、有一定的Java基础

4、熟悉Maven项目管理工具

任务实施

1、新建一个Maven工程

img

img

img

打开pom.xml文件,添加依赖:junit和mongodb的java驱动

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongodb-driver</artifactId>
			<version>3.12.10</version>
		</dependency>

	</dependencies>

2、resources目录下创建一个属性文件mongodb.properties,用来存储Mongdb数据库配置信息,内容如下:

host=localhost
port=27017
dbname=articledb

3、在包com.creatorblue.mongodb下新建辅助类MongoUtils.java,用于getMongoClient()获取MongoDB数据库的连接对象,定义一个getMongoConn()方法,用于实现连接指定的MongoDB数据库,内容如下:

private static Properties properties;
	private static MongoDatabase mongoDatabase;
	private static InputStream stream = null;
	private static String host;
	private static int port;
	private static String dbname;
	// 1.创建一个静态代码块,用于初始化工具类中的静态变量,该静态代码块在类加载过程中的初始化阶段 执行,并且只执行一次
	static {
		// 判断properties集合对象是否为空,为空则创建一个集合对象
		if (properties == null) {
			properties = new Properties();
		}
		/*
		 * 由于我们调用load方法,而load方法底层抛出了一个IOException异常,此异常为编译时期异常
		 * 所以,我们调用load方法时,需要处理底层抛过来的异常
		 */
		try {
			// 创建一个InputStream字节输入流对象,用于接收mongodb.properties配置文件中的配置参数
			stream = MongoUtils.class.getClassLoader().getResourceAsStream("mongodb.properties");
			// properties集合对象调用load()方法,将配置参数加载到properties集合中
			properties.load(stream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 根据mongodb.properties配置文件中的key,获取value值
		host = properties.getProperty("host");
		port = Integer.parseInt(properties.getProperty("port"));
		dbname = properties.getProperty("dbname");
	}

	// 2.定义一个getMongoClient()方法,用于获取MongoDB数据库的连接对象
	public static MongoClient getMongoClient() {
		// 由于MongoClients对象调用create()方法,该方法的参数是一个字符串,因此这里将host 和port拼接成字符串,再作为参数传入到该方法中
		String addr = "mongodb://" + host + ":" + port;
		MongoClient mongoClient = MongoClients.create(addr);
		return mongoClient;
	}

	// 3.定义一个getMongoConn()方法,用于实现连接指定的MongoDB数据库
	public static MongoDatabase getMongoConn() {
		MongoClient mongoClient = getMongoClient();
		mongoDatabase = mongoClient.getDatabase(dbname);
		return mongoDatabase;
	}
}

4、test目录下新建测试类TestMongo.java完成任务中的内容并验证

private static MongoDatabase mongoDatabase;
	    public static void main(String[] args) {
	        mongoDatabase = MongoUtils.getMongoConn();
	    }
	    /*
	    * 获取MongoDB中的所有数据库
	    */
	    @Test
	    public void getDBs() {
	        MongoClient mongoClient = MongoUtils.getMongoClient();
	        MongoIterable<String> databaseNames = mongoClient.listDatabaseNames();
	        for (String databaseName : databaseNames) {
	            System.out.println(databaseName);
	        }
	    }


	    /*
	    * 查看指定数据库(即数据库articledb)中的所有集合
	    * */
	    @Test
	    public void getCollection() {
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoIterable<String> listCollectionNames = mongoDatabase.listCollectionNames();
	        for (String collectionName : listCollectionNames) {
	            System.out.println(collectionName.toString());
	        }
	    }
	    /*
	    * 创建集合
	    */
	    @Test
	    public void createCollection(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        mongoDatabase.createCollection("creatorblue");
	    }
	    /*
	    * 删除集合
	    */
	    @Test
	    public void dropCollection(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoCollection<Document> itcast = mongoDatabase.getCollection("creatorblue");
	        itcast.drop();

	    }
	    /*
	     * 查看文档
	     * */
	    @Test
	    public void findDocument(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoCollection<Document> comment = mongoDatabase.getCollection("comment");
	        FindIterable<Document> documents = comment.find();
	        for (Document document : documents) {
	            System.out.println(document);
	        }
	    }


	    /*
	    * 插入一个文档
	    * */
	    @Test
	    public void insertOneDocument(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoCollection<Document> comment = mongoDatabase.getCollection("comment");
	        Document document = new Document("_id", "7").append("articleid","100001")
	                .append("content","吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助")
	                .append("userid","1007").append("nickname","玛丽莲•梦露").append("age","18")
	                .append("phone"," 13937165554").append("createdatetime",new Date())
	                .append("likenum","8888").append("state","null");
	        comment.insertOne(document);
	    }

	    /*
	     * 更新文档
	     * */
	    @Test
	    public void updateDocument(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoCollection<Document> comment = mongoDatabase.getCollection("comment");
	        Document document = new Document("content","饭后半小时最好不要喝大量的水,以免冲淡胃液,稀释胃酸,损害消化功能");
	                comment.updateOne(Filters.eq("content","吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有明显的帮助"),new Document("$set",document));
	    }

	    /*
	     * 删除文档
	     * */
	    @Test
	    public void deleteDocument(){
	        mongoDatabase = MongoUtils.getMongoConn();
	        MongoCollection<Document> comment = mongoDatabase.getCollection("comment");
	        comment.deleteOne(Filters.eq("_id","7"));
	    }

5、运行Junit测试类

img

6、查看articledb数据库 是否创建集合comment和creatorblue,comment集合中是否插入文档成功

img

实验实训

Springboot操作Mongodb

posted @ 2024-07-24 20:54  TechLearn  阅读(2)  评论(0编辑  收藏  举报
写代码、聊产品、懂设计、热爱阅读和分享
http://www.budaos.com