目录
一、MongoDB介绍
1.1 mongoDB介绍
- MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
- 在高负载的情况下,添加更多的节点,可以保证服务器性能。
- MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
- MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
1.2 特点
- MongoDB 是一个面向
文档存储
的数据库,操作起来比较简单和容易。 - 可以在MongoDB记录中设置任何属性的索引 (
如:id="1",name="goudan",Address="beijing"
)来实现更快查询或排序。 - 可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
- 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
- Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
- MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
- Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
- Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
- Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
- GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
- MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
- MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
- MongoDB安装简单。
1.3 MongoDB相关术语
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将==_id字段==设置为主键 |
通过下图实例,我们也可以更直观的了解Mongo中的一些概念:
二、安装部署
2.1 Docker安装MongoDB
2.1.1 下载
下载地址:MongoDB Enterprise Server Download | MongoDB
2.1.2 docker-ce安装
# 安装docker
# 默认repo源没有docker-ce安装包,需要新的repo源
# 安装依赖库,yum-utils 提供命令"yum-config-manager"
yum install -y yum-utils device-mapper-persistent-data lvm2
#设置添加阿里云镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 我们在更新yum源或者出现配置yum源之后,通常都会使用yum makecache 生成缓存
yum makecache fast# 安装最新版本的docker-ce即可
yum -y install docker-ce
docker --version
systemctl start/stop/status/restart docker#将docker和镜像重启
systemctl restart docker
systemctl daemon-reload# 为docker配置镜像加速
cat <<EOF > /etc/docker/daemon.json
{
"registry-mirrors": ["https://fzh5358h.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
# 设置开机自启,并重启
systemctl enable docker
systemctl restart docker
2.1.3 mongo镜像下载
#docker拉取mongo 4.4镜像
docker pull mongo:4.4
2.1.4 mongo容器创建并运行
[root@user1 local]# mkdir -p /usr/local/mongodb/data /usr/local/mongodb/conf /usr/local/mongodb/log
#运行docker容器(没有则创建),无需密码验证docker run \ -itd \ --name mongo \ -p 27017:27017 \ -v /usr/local/mongodb/data:/mongo/data \ -v /usr/local/mongodb/conf:/mongo/conf \ -v /usr/local/mongodb/log:/mongo/log \ mongo:4.4
docker run代表运行容器,没有就创建
-i: 允许你对容器内的标准输入 (STDIN) 进行交互
-t: 在新容器内指定一个伪终端或终端
-d: 在后台运行容器并打印containerID
--name: 指定容器名称
-p: 指定端口映射,即将容器的27107端口映射到本机27107
-v: 将本机的目录挂到容器内部/mongo/data目录
mongo:4.4:镜像名称
#创建mongo容器,后期登陆需要密码授权
docker run -itd --name mongo -p 27017:27017 mongo:4.4 --auth
--auth表示访问时需要密码
2.1.5 docker相关操作
# 查看容器列表
docker ps
#docker查看mongo日志,mongo为容器名称
docker logs mongo#停止mongo容器
docker stop mongo#列出镜像
docker image ls#列出容器
docker container ls#容器停止一个或者多个容器
docker container stop de845050dc24
docker container start de845050dc24 #开启一个或者多个容器
docker container restart de845050dc24 #重启一个或者多个容器
docker container run #重新运行一个新的容器#删除mongo容器
docker container rm de845050dc24
2.1.6 进入mongo容器
#无需账号登陆mongo,直接进入mongo容器内部,第一个mongo是容器名称,第二个是进入执行mongo
docker exec -it mongo mongo
MongoDB shell version v4.4.14
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("fa47f0cc-e8c2-44c7-aa90-49e1d9dfdd8f") }
MongoDB server version: 4.4.14
........
> db.collections;
test.collections
> exit;
#进入容器语法:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
#退出mongo容器
> exit;# 通过容器名称进入容器内部,并以admin账号登陆mongo
docker exec -it mongo mongo admin
# 容器内部执行指令
db.createUser({ user:'root',pwd:'123456',roles:[ { role:'root', db: 'admin'}]});
2.2 非Docker安装MongoDB
1)将mongodb-linux-x86_64-enterprise-rhel70-4.4.14.tgz通过MobaXterm_CHS上传至
/root/softwares 下通过命令将压缩包接到usr/local
tar -zxvf /root/softwares/mongodb-linux-x86_64-enterprise-rhel70-4.4.14.tgz -C /usr/local
2)重命名
mv /usr/local/mongodb-linux-x86_64-enterprise-rhel70-4.4.14/ /usr/local/mongodb
3)创建数据、配置、日志目录
mkdir -p /usr/local/mongodb/data /usr/local/mongodb/conf /usr/local/mongodb/log
在mongodb 下的bin建立配置文件夹
vi /usr/local/mongodb/conf/mongodb.conf
然后输入
# mongodb 配置文件 port=27017 #端口 bind_ip=0.0.0.0 #默认是127.0.0.1 dbpath=/usr/local/mongodb/data #数据库存放 logpath=/usr/local/mongodb/log/mongodb.log #日志文件 fork=true #设置后台运行 #auth=true #开启认证
4)启动mongodb
[root@user1 mongodb]# /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/conf/mongodb.conf
#如果启动报错
/usr/local/mongodb/bin/mongod: error while loading shared libraries: libnetsnmpmibs.so.31: cannot open shared object file: No such file or directory
#解决方案为:安装如下的依赖再次启动MongoDB
yum -y install net-snmp#启动完可以先本地连接
#连接客户端
[root@user1 mongodb]# /usr/local/mongodb/bin/mongo
2.3 通过Navicat Premium15连接mongoDB
进入Navicat Premium15-->左上角文件-->新建连接-->MongoDB
输入连接名及主机IP后点击确定
连接成功
三、MongoDB操作
3.1 数据库操作
- 一个mongodb中可以建立多个数据库。
-
MongoDB的
默认数据库为"test"
,该数据库存储在data目录中。 - MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
1)通过show dbs命令查看现有数据库
#显示所有数据的列表
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
- admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
- local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
2)通过db命令显示当前所在数据库对象或集合
> db
test
3)通过use命令连接到一个已存在的数据库或新创建一个数据库
> use local
local
刚创建的数据库 mydb并不在数据库的列表中, 要显示它,需要向新创建的数据库插入一些数据。
4)通过db.dropDatabase()删除当前数据库
#删除当前数据库,默认为 test,可以使用 db 命令查看当前数据库名
> db
local
> db.dropDatabase()
3.2 集合操作
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统)中的表(table)。
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
比如,我们可以将以下不同数据结构的文档插入到集合中:
{"id":1}
{"id":1,"name":"zhangsan"}
{"id":1,"name":"zhangsan", "address":"beijing"}
1) Collection的创建
创建有两种方式:
方法一:db.createCollection(name, options)
参数说明:
- name: 要创建的集合名称
- options: 可选参数, 指定有关内存大小及索引的选项。options 有如下的参数: 在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段
字段
类型
描述
capped
布尔
(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。
autoIndexId
布尔
3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。
size
数值
(可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。
max
数值
(可选)指定固定集合中包含文档的最大数量
> use mydb
switched to db mydb
> db.createCollection("myct1")
方法二:db.collection.insert({})
当第一个文档插入时,集合就会被创建,这里的collection可以是不存在的,如:
db.myct2.insert({"name":"Lisan","age":20})
2)通过show collections 或 show tables命令查看当前数据库下的表
> show collections
myct1
myct2
3) 通过db.collection.drop()删除指定的collection(表)
#如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
> db.myct2.drop()
true
4)通过db.collection.find()来查看表中的文档
后面再跟.pretty()为格式化查询,展示效果更美观,后面在文档部分中会专门介绍。
3.3 文档操作
3.3.1 文档介绍
- 文档的数据结构和 JSON 基本一样。
- 所有存储在集合中的数据都是 BSON 格式。
- BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
- 文档是一组键值(key-value)对(即 BSON),一个简单的文档例子如下:{"id":1,"name":"zhangsan", "address":"beijing"}
3.3.2 MongoDB 数据类型
数据类型 | 描述 |
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression | 正则表达式类型。用于存储正则表达式。 |
特别地,ObjectId
ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
- 前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
- 接下来的 3 个字节是机器标识码
- 紧接的两个字节由进程 id 组成 PID
- 最后三个字节是随机数
MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象
#由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:
> var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2022-05-10T10:17:55Z")#ObjectId 转为字符串
> newObject.str
62a46bd34c256eb2b320f207
3.3.3 插入文档
MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:
db.COLLECTION_NAME.insert(document)
或
db.COLLECTION_NAME.insertOne() 和 db.COLLECTION_NAME.insertMany() #3.2 版本之后新增
或
db.COLLECTION_NAME.save(document)
- save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
- insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
db.collection.insertMany() 用于向集合插入一个新文档,语法格式如下:
db.collection.insertMany(
[ <document 1> , <document 2>, ... ], -- insertOne()时这儿就一个文档,不需要数组即可
)
写入案例
-- myct1中添加1个文档
> db.myct1.insert({"id":1,"name":"goudan", "address":"beijing"})-- myct1中添加1个文档
> db.myct1.insertOne({"id":2,"name":"mz", "address":"beijing"})-- myct1中添加2个文档
> db.myct1.insertMany([{"id":3,"name":"shanjige", "address":"beijing"}-- myct1中添加1个文档
> db.myct1.save({"id":5,"name":"renzha", "address":"tangshan"})> db.myct1.find()
{ "_id" : ObjectId("62a46dee4c256eb2b320f208"), "id" : 1, "name" : "goudan", "address" : "beijing" }
{ "_id" : ObjectId("62a46e194c256eb2b320f209"), "id" : 2, "name" : "mz", "address" : "beijing" }
{ "_id" : ObjectId("62a46e644c256eb2b320f20a"), "id" : 3, "name" : "shanjige", "address" : "beijing" }
{ "_id" : ObjectId("62a46e644c256eb2b320f20b"), "id" : 4, "name" : "haonan", "address" : "jianshazui" }
{ "_id" : ObjectId("62a46eae4c256eb2b320f20c"), "id" : 5, "name" : "renzha", "address" : "tangshan" }
3.3.4 MongoDB更新文档
MongoDB 使用 update() 和 save() 方法来更新集合中的文档。
update() 更新
使用update() 方法更新已存在的文档,语法格式如下:
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 :可选,抛出异常的级别。
-- 更新name值zhangsan为zs
> db.myct1.update({"name":"zhangsan"},{$set:{"name":"zs"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
save() 更新
save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。
-- 更新文档name值zhangsan为zs
> db.myct1.save({ "_id" : ObjectId("62a46eae4c256eb2b320f20c"), "name" : "rz","age":18})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
注意:使用save方法所有的数据字段均要包括,因为他是覆盖,如果上面只改了name而后面没有加age,新的文档里没有age这个字段。
3.3.5 MongoDB 查询文档
MongoDB 查询文档使用 find() 方法。
find() 方法以非结构化的方式来显示所有文档。find()查询数据的语法格式如下:
db.collection.find(query, projection)[.pretty()]
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
- .pretty() : 美化查询结果。
- 除find()外,还有findOne() 方法,它只返回一个文档。
MongoDB 与 RDBMS Where 语句比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
等于 |
} |
|
|
小于 |
|
|
|
小于或等于 |
|
|
|
大于 |
|
|
|
大于或等于 |
|
|
|
不等于 |
|
|
|
MongoDB and条件
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。
语法格式如下:
>db.col.find({key1:value1, key2:value2}).pretty()
MongoDB OR 条件
MongoDB OR 条件语句使用了关键字 $or,语法格式如下:
>db.col.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
查询案例
-- 查询myTable所有数据
> db.myct1.find()-- 查询myTable name=sjg的数据
> db.myct1.find({"name":"sjg"})-- 查询myTable name=sjg and address=beijing的数据
> db.myct1.find({"name":"sjg","address":"beijing"})-- 查询myTable name = sjg or address=beijing的数据
> db.myct1.find({$or:[{"name":"sjg"},{"address":"beijing"}]})-- 查询myTable id > 1 and (name=sjg or address=beijing)的数据
> db.myct1.find({"id":{$gt:1},$or:[{"name":"sjg"},{"address":"beijing"}]})-- 查询myTable第一条数据
> db.myct1.findOne()-- 查询myTable满足name=sjg or address=beijing条件的第一条数据
> db.myct1.findOne({$or:[{"name":"sjg"},{"address":"beijing"}]})
3.3.6 MongoDB中limit和skip
MongoDB Limit() 方法
如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。limit()方法基本语法如下所示:
>db.COLLECTION_NAME.find().limit(NUMBER)
MongoDB Skip() 方法
我们除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。skip() 方法脚本语法格式如下:
>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER) -- skip默认数量为0
查询案例
> db.myct1.find().limit(2)
> db.myct1.find().limit(2).skip(2)
3.3.7 聚合查询
MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果,有点类似 SQL 语句中的 count(*)。
aggregate() 方法
MongoDB中聚合的方法使用aggregate()。aggregate() 方法的基本语法格式如下所示:
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
查询案例
-- 根据address过滤,统计每个城市人数
> db.myct1.aggregate([{$group : {_id : "$address", addr_users : {$sum : 1}}}]){ "_id" : "tangshan", "addr_users" : 1 }
{ "_id" : "jianshazui", "addr_users" : 1 }
{ "_id" : "beijing", "addr_users" : 3 }-- 查询总的数据条数
> db.myTable.count()
5
3.3.8 文档删除
官方推荐使用 deleteOne() 和 deleteMany() 方法。
删除 name 等于zhangsan的全部文档:
> db.myct1.deleteMany({ name : "zhangsan" })
{ "acknowledged" : true, "deletedCount" : 1 }
删除集合下全部文档:
> db.myTable.deleteMany({})
3.3.9 通过Navicat Premium15可视化工具操作