第二部分:关键技术领域的开源数据库实践【开源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中的四大家族主要是:列存储、键值、图像存储、文档存储,其类型产品主要有以下这些。
NOSQL的优势
NoSQL的优点/缺点
优点:
- - 高可扩展性
- - 分布式计算
- - 低成本
- - 架构的灵活性,半结构化数据
- - 没有复杂的关系
缺点:
- - 没有标准化
- - 有限的查询功能(到目前为止)
- - 最终一致是不直观的程序
NOSQL与RDBMS对比
RDBMS vs NoSQL
MongoDB简介
MongoDB,Redis 是NO-SQL的杰出代表。是大数据,人工智能、分布式应用、高速缓存应用场景必备技能。
MongoDB是什么
MongoDB并非芒果的意思,而是源于 Humongous(巨大)一词。中文叫盲狗*db*
MongoDB是面向文档的数据库,不是关系型数据库。它将原来*‘行’(row)的概念换成了更加灵活的‘文档’(document)模型*。面向文档的方式可以将文档和数组内嵌进来,所以用一条记录就可以表示很复杂的层次关系。 MongoDB没有模式,文档的键不会事先定义也不会固定不变。**
*Mongodb主要由文档(Document)、集合(Collection)、数据库(Database)三部分组成。*
一个MongoDB实例,由多个数据库(Database)组成;一个数据库,由多个集合(Collection)组成;一个集合,又由多个文档组成。注意Mongodb单个文档大小上限为16MB,确保不会使用过多的内存RAM或在传输过程中占用过多的带宽。为了存储更大的文档,Mongodb提供了GridFS。
作为开始,我们需要了解6个简单的概念:
- MongoDB有着与您熟知的‘数据库’(database,对于Oracle就是‘schema’)一样的概念。在一个MongoDB的实例中您有若干个数据库或者一个也没有,不过这里的每一个数据库都是高层次的容器,用来储存其他的所有数据。
- 一个数据库可以有若干‘集合’(collection),或者一个也没有。集合和传统概念中的‘表’有着足够多的共同点,所以您大可认为这两者是一样的东西。
- 集合由若干‘文档’(document)组成,也可以为空。类似的,可以认为这里的文档就是‘行’。
- 文档又由一个或者更多个‘域’(field)组成,您猜的没错,域就像是‘列’。
- ‘索引’(index)在MongoDB中的意义就如同索引在RDBMS中一样。
- ‘游标’(cursor)和以上5个概念不同,它很重要但是却常常被忽略,有鉴于此我认为应该进行专门讨论。关于游标有一点很重要,就是每当向MongoDB索要数据时,它总是返回一个游标。基于游标我们可以作诸如计数或是直接跳过之类的操作,而不需要真正去读数据。
小结一下,MongoDB由‘数据库’组成,数据库由‘集合’组成,集合由‘文档’组成。‘域’组成了文档,集合可以被‘索引’,从而提高了查找和排序的性能。最后,我们从MongoDB读取数据的时候是通过‘游标’进行的,除非需要,游标不会真正去作读的操作。
程序员注重对象,您的数据库也是。
MongoDB 是一个文档数据库,即在类似 JSON 的文档内存储数据。我们认为面对数据,这种方法非常自然,比传统的排/列模型更加直观和强大。
丰富的 JSON 文档
自然、高效的数据处理方法。
支持将数组和嵌套对象存储为值。
支持灵活、动态结构。
强大的查询语言
查询语言丰富和直观,支持通过任何字段进行筛选和排序,而不受其在文档内的嵌套方式影响。
支持聚合和其他现代使用案例,如基于地理的搜索、图搜索和文本搜索。
查询本身是 JSON 格式,因此很容易进行组合。无需串联字符串即可动态生成 SQL 查询。
MongoDB的特性
MongoDB的3大技术特色如下所示:
除了上图所示的还支持:
二级索引、动态查询、全文搜索 、聚合框架、MapReduce、GridFS、地理位置索引、内存引擎 、地理分布等一系列的强大功能。
但是其也有些许的缺点,例如:
多表关联: 仅仅支持Left Outer Join
SQL 语句支持: 查询为主,部分支持
多表原子事务: 不支持
多文档原子事务:不支持
16MB 文档大小限制,不支持中文排序 ,服务端 Javascript 性能欠佳
关系数据库与MongoDB的区别
存储方式对比
在传统的关系型数据库中,存储方式是以表的形式存放,而在MongoDB中,以文档的形式存在。
数据库中的对应关系,及存储形式的说明
MongoDB与SQL的结构对比详解
MongoDB数据存储格式
JSON****格式
JSON 数据格式与语言无关,脱胎于 JavaScript,但目前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。
MongoDB 使用JSON(JavaScript ObjectNotation)文档存储记录。
JSON数据库语句可以容易被解析。
Web 应用大量使用,NAME-VALUE 配对
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数据的存储。
MongoDB 慎用场景
什么时候该MongDB
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数据库注意的事项:
- 一定要用管理员的身份运行
- 安装目录严禁使用中文目录
- 数据data目录更改到非系统盘,确保数据安全
- 默认27017端口,如果端口占用请更改netstat -a查看
1、双击msi安装包
取消MongoDB Compass的安装选项(不取消安装极慢),需要可自行安装;
直至100%完成
MongoDB默认提供admin、Local、config以及test四个数据库,具体如下:
- admin数据库,主要存储数据库账号的相关信息
- local数据库,可以用于存储限于本地单台服务器的任意集合,如oplog日志就存储在local数据库中,该数据库的数据不会被 复制到从结点上
- config数据库,用于存储分片集群中与分片相关的元数据信息
- 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下默认的几个数据库文件,可以查看是否已经生成
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
解决办法:
然后重新启动mongodb服务即可
管理MongoDB
安装完成后,查询Mongodb系统服务mongoDB
方法一:自动启动mongodb数据库
Mongodb常用的命令
如果想关闭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
连接MongoDB命令
例如:安装在C:\Program Files\MongoDB\Server\5.0\bin目录,先进入此目录,再执行如下命令
./mongo 127.0.0.1:27017
出现“>”号表示mogodb已正常启动
方法二:手动启动mongo数据库
1、启动数据库mongod(服务器端)
2、客户端连接 mongo
客户端工具
MongoDB客户端工具推荐:
1、NoSQL Manager for MongoDB Freeware
https://www.mongodbmanager.com/download
- 工具栏介绍
- New MongoDB Connection:打开连接数据库页面
- Shell:打开命令行操作页面
- 打开连接数据库页面
- 命令行操作页面
- F5:执行全部命令
- F6:执行某一行命令,光标放在那一行上面
- F9:执行选择的命令
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默认三个数据库,需要显示隐藏的项目
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
四、集合的重命名
db.role.renameCollection('user')
文档操作
插入文档
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({
查询的条件,
更新的语句,
附加的参数
})
附加的参数
db.student.insertMany([
{
"stu_name" : "小张",
"stu_number" : "2013003",
},
{
"stu_name" : "小张",
"stu_number" : "2013002",
},
{
"stu_name" : "小张三",
"stu_number" : "2013004"
}]
)
区分:update默认情况下是只修改一个文档,等同updateOne,如果需要修改多个可以使用multi:true属性
- db.collection.update(query, update);
db.student.update(
{
"stu_name" : "小张"
},
{
$set : {"stu_name" : "小张二"}
}
)
- db.collection.updateOne(query, update);
db.student.update(
{
"stu_name" : "小张"
},
{
$set : {"stu_name" : "小张一"}
}
)
修改多个文档
db.student.update(
{
"stu_name": "小张"
},
{
$set: {
"stu_name": "小张二"
}
},
{
multi: true
}
)
- 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({
条件
},属性)
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。
$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
- 表达式
- $sum
- $avg
- $min
- $max
- $push: 数组
- $first
- $last
- $$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文件导入到数据库中
下载地址:
2、导入方法
特别注意下要确定好导的数据类型的选择,像一般工资属于数值型
然后默认下一步,直至最后完成!
独立完成以下练习
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工程
打开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测试类
6、查看articledb数据库 是否创建集合comment和creatorblue,comment集合中是否插入文档成功