MongoDB
本文最后更新于:2021年6月8日 下午
信息
MongoDB
是一个由C++
编的 写基于分布式文件存储的数据库。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案MongoDB
是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的
存储
MongoDB
将数据存储为一个文档,数据结构由键值对组成MongoDB
文档类似于 JSON
对象。字段值可以包含其他文档,数组及文档数组
特点
MongoDB
是一个面向文档存储的数据库,操作起来比较简单和容易- MongoDB记录中设置任何属性的索引来实现更快的排序
- 可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性
- 如果负载的增加 ,它可以分布在计算机网络中的其他节点上这就是所谓的分片
- Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组
- 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段
- Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理
- Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作
- GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件
- MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用
链接
安装
Docker安装
拉取镜像
1 |
|
如果想要安装非最新版,可以查询Docker镜像信息信息
或者使用docker search mongo
来查看可用版本
在拉取完毕后,可以使用docker images
来查看镜像信息
运行容器
1 |
|
參數説明:
- -p 27018:27017
映射容器服务的27017
端口到宿主机的27018
端口。外部可以直接通过ip:27018
访问到mongo
的服务 - –auth
需要密码才能访问容器服务 - -itd
实际上是-i
-t
-d
的简写-i
以交互模式运行容器,通常与-t
同时使用-t
为容器重新分配一个伪输入终端,通常与-i
同时使用-d
后台运行容器,并返回容器ID
可以通过docker ps
命令查看容器的运行信息
初始化
进入容器控制台
1 |
|
创建一个超级账户
1 |
|
在创建完用户以后尝试使用新用户进行连接
1 |
|
如果正确可行的话,会返回1,这也意味着账户切换成功
其它创建账户
1 |
|
可用角色类型:
- 数据库用户角色(Database User Roles)
- read:授予User只读数据的权限
- readWrite:授予User读写数据的权限
- 数据库管理角色(Database Administration Roles)
- dbAdmin:在当前dB中执行管理操作
- dbOwner:在当前DB中执行任意操作
- userAdmin:在当前DB中管理User
- 备份和还原角色(Backup and Restoration Roles)
- backup
- restore
- 跨库角色(All-Database Roles)
- readAnyDatabase:授予在所有数据库上读取数据的权限
- readWriteAnyDatabase:授予在所有数据库上读写数据的权限
- userAdminAnyDatabase:授予在所有数据库上管理User的权限
- dbAdminAnyDatabase:授予管理所有数据库的权限
MongoDB名词概念
SQL术语/概念 | MongoDB术语/概念 |
---|---|
database 数据库 | database 数据库 |
table 数据库表 | collection 集合 |
row 数据记录行 | document 文档 |
column 数据字段 | field 域 |
index 索引 | index 索引 |
table joins表连接 | 不支持 |
primary key 主键 | primary key MongoDB自动将_id字段设置为主键 |
数据库 database
一个mongodb
中可以建立多个数据库MongoDB
的默认数据库为”db”,该数据库存储在data目录中MongoDB
的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中
数据库命名
数据库名为utf-8字符串,符合以下标准:
- 非空
- 不含(空格)、.、$、/、\和\0 (空字符)
- 字母全部小写
- 小于64字节
常用操作
命令 | 信息 |
---|---|
show dbs |
查询所有含有文档的数据库信息 |
db |
显示当前数据库信息 |
use 数据库名 |
连接到指定数据库如果数据库不存在则创建数据库 |
db.dropDatabase() |
删除当前数据库 |
保留的数据库
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
保留数据库名 | 信息 |
---|---|
admin | 从权限的角度来看,这是”root”数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器 |
local | 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合 |
config | 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息 |
集合 Collection
常用操作
创建集合
1 |
|
name:集合名
option:可选参数
capped(bool)
如果为 true,则创建固定集合。为 true 时,必须指定 size 参数固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档
size (int)
为固定集合指定一个最大值,即字节数
如果 capped 为 true,也需要指定该字段max (int)
指定固定集合中包含文档的最大数量
案例: 创建集合
1 |
|
查看集合
命令有两个,随便一个都可以
1 |
|
删除集合
1 |
|
案例: 删除集合
1 |
|
文档 Document
文档的数据结构和 JSON 基本一样
所有存储在集合中的数据都是 BSON
格式BSON
是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON
的简称
- 文档不需要设置相同的字段,相同的字段不需要相同的数据类型
- 文档中的键/值对是有序的
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)
- 区分类型和大小写
- 文档不能有重复的键
- 文档的键是字符串。除了少数例外情况,键可以使用任意
UTF-8
字符
文档键命名规范
- 键不能含有\0 (空字符)。这个字符用来表示键的结尾
- 用
.
分层 - $有特别的意义,只有在特定环境下才能使用
- 以下划线
_
开头的键是保留的(不是严格要求的)
常用操作
插入
db.collection.insertOne
作用:如果主键存在则更新数据,如果不存在就插入数据
1 |
|
- document:要写入的文档
- writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求
- ordered:指定是否按顺序写入,默认 true,按顺序写入
案例: 插入文档
1 |
|
db.collection.insertMany
作用:向集合插入一个多个文档
1 |
|
参数与db.collection.insertOne
一致
案例 往 products集合 插入一些数据
1 |
|
db.collection.insert()
若插入的数据主键已经存在,则会抛org.springframework.dao.DuplicateKeyException
异常,提示主键重复,不保存当前数据
案例:向 runoob 数据库 的 col 集合中插入数据
1
2
3
4
5
6
7
db.col.insert({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
删除
db.collection.deleteOne
删除集合中的一个文档1
2
3
4
5
6
7
8db.collection.deleteOne(
<filter>,
{
writeConcern: <document>,
collation: <document>,
hint: <document|string> // Available starting in MongoDB 4.4
}
)- filter
指定删除条件,如果设置为{}则删除第一个文档 - writeConcern
可选参数,写入关注,其值为一个文档 - collation
可选参数,指定用于操作的集合 - hint
可选参数,指定用于支持查询谓词的索引的文档或字符串
假设现在有一个order集合,集合中有这么个文档
1
2
3
4
5
6
7
8
9
10{
_id: ObjectId("563237a41a4d68582c2509da"),
stock: "Brent Crude Futures",
qty: 250,
type: "buy-limit",
limit: 48.90,
creationts: ISODate("2015-11-01T12:30:15Z"),
expiryts: ISODate("2015-11-01T12:35:15Z"),
client: "Crude Traders Inc."
}案例: 根据删除
_id
为233
的文档1
db.orders.deleteOne( { "_id" : ObjectId("233") } );
- filter
db.collection.deleteMany
删除集合中所有符合filter
的文档
文档地址1
2
3
4
5
6
7db.collection.deleteMany(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)参数同
db.collection.deleteOne
案例
假设现在有一个order集合,集合中有这么个文档1
2
3
4
5
6
7
8
9
10{
_id: ObjectId("563237a41a4d68582c2509da"),
stock: "Brent Crude Futures",
client: "Crude Traders Inc."
}
{
_id: ObjectId("123437a41a423423444509da"),
stock: "Brent Crude Futures",
client: "Crude Traders Inc."
}案例: 根据删除
client
为Crude Traders Inc.
的文档1
db.orders.deleteMany( { "client" : "Crude Traders Inc." } );
更改
db.collection.update
作用:更新已存在的文档
使用格式
1 |
|
- query : update的查询条件,类似sql update查询内where后面的
- update : update的对象和一些更新的操作符(如$,$inc…)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
- writeConcern :可选,抛出异常的级别
案例:更改
title
为mysql
假设现在有一个order集合,集合中有这么个文档
1 |
|
更改title
为mysql
1 |
|
需要注意的是,这语句只会修改第一个发现的文档
如果想要修改多个,需要添加 {multi:true}
1 |
|
官方文档説明:https://docs.mongodb.com/master/reference/command/update/
db.collection.save
作用:通过传入的文档来替换已有文档,主键存在就更新,不存在就插入
1 |
|
- document : 文档数据
- writeConcern :可选,抛出异常的级别
实际上就是用一个新的文档来覆盖旧的,关键是要让_id主键一致
1 |
|
查询
db.collection.find
1 |
|
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)
如果你希望返回比较好看的形式,可以用pretty
1 |
|
实际上还有一个 findOne
方法专门用来找单个文档
限制查询数量 Limit
如果你需要在MongoDB
中读取指定数量的数据记录,可以使用MongoDB
的Limit
方法limit()
方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数
未指定limit
方法中的参数则显示集合中的所有数据
1 |
|
案例:查找前两条数据
1 |
|
跳过查询数量 Skip()
除了可以使用limit
方法来读取指定数量的数据外,还可以使用skip
方法来跳过指定数量的数据
skip方法同样接受一个数字参数作为跳过的记录条数。默认参数为 0
案例:查找第二条数据
1 |
|
1 |
|
排序 sort()
sort
方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式
1 为升序排列,而 -1 是用于降序排列
1 |
|
Filter
比较逻辑
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key> :<value> } |
db.col.find({“by”:”123”}).pretty() | where by = ‘123’ |
小于 | {<key> :{$lt:<value> }} |
db.col.find({“likes”:{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key> :{$lte:<value> }} |
db.col.find({“likes”:{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key> :{$gt:<value> }} |
db.col.find({“likes”:{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key> :{$gte:<value> }} |
db.col.find({“likes”:{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key> :{$ne:<value> }} |
db.col.find({“likes”:{$ne:50}}).pretty() | where likes != 50 |
逻辑运算
and 与逻辑
同时传入多个键即可
1 |
|
or 或逻辑
使用关键词$or
1 |
|
not 非逻辑
使用关键词$not
1 |
|
$type
操作符
$type
操作符是基于BSON
类型来检索集合中匹配的数据类型,并返回结果
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1 |
Max key | 127 |
案例:寻找标题为字符串类型的文档
1 |
|
多集合查询
实际上,多集合查询是利用聚合的 $lookup
多表关联 实现的
具体见后
索引
索引通常能够极大的提高查询的效率
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的
常用操作
创建
1 |
|
参数 | 值类型 | 信息 |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
案例:以
title
键建立索引
1 |
|
案例:以
title
与name
键在后台建立索引
1 |
|
通过在创建索引时加 background:true
的选项,让创建工作在后台执行
查看
- 查看集合索引
1
db.col.getIndexes()
- 查看集合索引大小
1
db.col.totalIndexSize()
删除
- 删除集合所有索引
1
db.col.dropIndexes()
- 删除集合指定索引
1
db.col.dropIndex("索引名称")
聚合
MongoDB
中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果
aggregate() 方法
MongoDB中聚合的方法使用 aggregate()
1 |
|
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 在结果文档中插入值到一个数组中 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
案例:计算每个作者所写的文章数
1 |
|
1 |
|
管道的概念
管道在Unix
和Linux
中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB
的聚合管道将MongoDB
文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
聚合框架中常用操作:
运算符 | 信息 |
---|---|
$project | 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档 |
$match | 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作 |
$limit | 用来限制MongoDB聚合管道返回的文档数 |
$skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档 |
$unwind | 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值 |
$group | 将集合中的文档分组,可用于统计结果 |
$sort | 将输入文档排序后输出 |
$geoNear | 输出接近某一地理位置的有序文档 |
$lookup | 多表关联 |
案例:结果中只有_id,tilte和author三个字段
1 |
|
实际上有还有一个默认添加的字段_id
,如果想要取消指定_id:0
即可
$lookup
多表查询
主要功能
处理每个输入的文档,输出的新文档中会包含一个新生成的数组列(户名可根据需要命名新key的名字),如果没有内容适配,集合为空(即[ ]
)
语法
1 |
|
语法值 | 解释说明 |
---|---|
from | 同一个数据库中等待被 Join 的集合 |
localField | 被Join 集合中的 键如果集合中的某个文档没有这个键,那么就认为其实这个文档有这个键,只是个键的值为 null |
foreignField | 要Join 的集合的 键如果集合中的某个文档没有这个键,那么就认为其实这个文档有这个键,只是个键的值为 None |
as | 为输出文档的新增键命名 如果输入的集合中已存在该值,则会覆盖掉 |
例: 查询武器的所有信息
1 |
|
进行聚合计算
1 |
|
得到结果
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!