目录
之前学过Nosql中的Redis,所以就也想把MongoDB也学习一下,MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库(nosql)之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
什么是NoSQL?
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
为什么使用NoSQL ?
今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。
RDBMS vs NoSQL
RDBMS
- 高度组织化结构化数据
- 结构化查询语言(SQL) (SQL)
- 数据和关系都存储在单独的表中。
- 数据操纵语言,数据定义语言
- 严格的一致性
- 基础事务
NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言
- 没有预定义的模式
-键 - 值对存储,列存储,文档存储,图形数据库
- 最终一致性,而非ACID属性
- 非结构化和不可预知的数据
- CAP定理
- 高性能,高可用性和可伸缩性
CAP定理(CAP theorem)
在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
- CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
- CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
- AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
NoSQL的优点/缺点
优点:
- - 高可扩展性
- - 分布式计算
- - 低成本
- - 架构的灵活性,半结构化数据
- - 没有复杂的关系
缺点:
- - 没有标准化
- - 有限的查询功能(到目前为止)
- - 最终一致是不直观的程序
NoSQL 数据库分类
什么是MongoDB ?
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
主要特点
- MongoDB的提供了一个面向文档存储,操作起来比较简单和容易。
- 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")来实现更快的排序。
- 你可以通过本地或者网络创建数据镜像,这使得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 概念解析
不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下面我们挨个介绍。
下表将帮助您更容易理解Mongo中的一些概念:
通过下图实例,我们也可以更直观的的了解Mongo中的一些概念:
window平台安装 MongoDB
MongoDB 下载
MongoDB提供了可用于32位和64位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB预编译二进制包下载地址:https://www.mongodb.com/download-center/community
根据你的系统下载 32 位或 64 位的 .msi 文件,下载后双击该文件,按操作提示安装即可。
安装,接下来为了避免掉坑,肯定是打开官方文档,按照文档进行安装咯。安装步骤如下:
双击安装包,一路Next,直到选择安装位置,可以继续Next也可以自定义安装位置(Custom),我选择将其装到C盘根目录下(C:\MongoDB)
继续一路Next,直到完成。
配置运行:
1.在第四步的MongoDB服务依旧开启的情况下,再以管理员身份运行一个新的cmd窗口,键入以下命令,cmd出现可输入的光标即连接成功:
"C:\Program Files\MongoDB\Server\4.0\bin\mongo.exe"
2.进入log目录(C:\Program Files\MongoDB\Server\4.0\log),打开mongod.log,如果看到有下面这一行,就是启动成功:[initandlisten] waiting for connections on port 27017
3.创建数据存储目录,比如D:\MongoData\db,建议不要和安装目录相同,防止以后数据库升级出现问题;
可以使用--dbpath选项为mongod.exe指定数据文件的备用路径,例如:
"C:\Program Files\MongoDB\Server\4.0\bin\mongod.exe" --dbpath "D:\MongoData\db"
启动MongoDB
要启动 MongoDB,请运行 mongod.exe
。 例如,从命令提示符:
"C:\Program Files\MongoDB\Server\4.0\bin\mongod.exe"
打开 MongoDB 客户端测试使用
将MongoDB添加到环境变量(可选):新建系统变量MONGODB_HOME,值为C:\Program Files\MongoDB ,在Path变量下添加 %MONGODB_HOME%\Server\4.0\bin;
MongoDB统计
要获取有关MongoDB服务器的统计信息,请在 MongoDB 客户端中键入命令:db.stats()
。 这个命令将显示数据库名称,数据库中的集合和文档数量。命令的输出如下面的截图所示 -
MongoDB中的数据具有灵活的模式。文档在同一集合,但它们不需要具有相同的字段或结构集合,集合文档中的公共字段可以包含不同类型的数据。
MongoDB中的数据具有灵活的模式。与SQL数据库不同,SQL数据库必须在插入数据之前确定和声明表的模式,MongoDB的集合不会强制执行文档结构。这种灵活性有助于将文档映射到实体或对象。 每个文档可以匹配表示实体的数据字段,即使数据具有实质性的变化。然而,集合中的文档具有类似的结构。
数据建模中的关键挑战是平衡应用程序的需求,数据库引擎的性能特征和数据检索模式。 在设计数据模型时,请始终考虑数据的应用程序使用情况(即数据的查询,更新和处理)以及数据本身的固有结构。
在MongoDB中设计架构时有一些考虑:
- 根据用户要求设计架构。
- 将对象合并到一个文档中,否则分开它们(但确保不需要连接)。
- 复制数据(但有限制),因为与计算时间相比,磁盘空间便宜。
- 在写入时加入,而不是读取时加入。
- 为最常用的用例优化架构。
- 在模式中执行复杂聚合。
实例
假设客户需要他的博客/网站的数据库设计,并查看RDBMS和MongoDB架构设计之间的区别。网站有以下要求。
- 每个帖子都有唯一的标题,描述和网址。
- 每个帖子都可以有一个或多个标签。
- 每个帖子都有其发布者的名称和总人数。
- 每个帖子都有用户给出的评论以及他们的姓名,消息,数据时间和喜好。
- 每个帖子可以有零个或多个评论。
在RDBMS架构中,上述要求的设计将具有最少的三个表。表与表之间的关系如下 -
而在MongoDB模式中,设计将有一个集合post
,其结构以下 -
通过上面的示例说明可以知道,在显示数据时,在RDBMS中需要连接三个表,而在MongoDB中,数据将仅显示在一个集合中。
MongoDB创建数据库
use 命令
MongoDB使用 use DATABASE_NAME
命令来创建数据库。如果指定的数据库DATABASE_NAME
不存在,则该命令将创建一个新的数据库,否则返回现有的数据库。
语法
use DATABASE
语句的基本语法如下 -
示例
如果要创建一个名称为<newdb>
的数据库,那么使用 use DATABASE
语句将如下所示:
要检查当前选择的数据库,请使用 db
命令 -
如果要检查数据库列表,请使用命令:show dbs
。
创建的数据库(newdb
)不在列表中。要显示数据库,需要至少插入一个文档,空的数据库是不显示出来的。
在 MongoDB 中默认数据库是:test
。 如果您还没有创建过任何数据库,则集合/文档将存储在test
数据库中。
MongoDB删除数据库
db.dropDatabase() 方法
MongoDB中的 db.dropDatabase()
命令用于删除现有的数据库。
这将删除当前所选数据库。 如果没有选择任何数据库,那么它将删除默认的’test
‘数据库。
示例
首先,使用命令show dbs
检查可用数据库的列表。
如果要删除新数据库<newdb>
,那么dropDatabase()
命令将如下所示:
现在检查数据库列表,如下 -
MongoDB创建集合:
我们将学习如何在 MongoDB 中创建一个集合。
createCollection()方法
MongoDB 的 db.createCollection(name,options)
方法用于在MongoDB 中创建集合。
语法
createCollection()
命令的基本语法如下 -
在命令中,name
是要创建的集合的名称。 options
是一个文档,用于指定集合的配置。
参数 | 类型 | 描述 |
---|---|---|
name | String | 要创建的集合的名称 |
options | Document | (可选)指定有关内存大小和索引的选项 |
options
参数是可选的,因此只需要指定集合的名称。 以下是可以使用的选项列表:
字段 | 类型 | 描述 |
---|---|---|
capped | Boolean | (可选)如果为true ,则启用封闭的集合。上限集合是固定大小的集合,它在达到其最大大小时自动覆盖其最旧的条目。 如果指定true ,则还需要指定size 参数。 |
autoIndexId | Boolean | (可选)如果为true ,则在_id 字段上自动创建索引。默认值为false 。 |
size | 数字 | (可选)指定上限集合的最大大小(以字节为单位)。 如果capped 为true ,那么还需要指定此字段的值。 |
max | 数字 | (可选)指定上限集合中允许的最大文档数。 |
在插入文档时,MongoDB首先检查上限集合capped
字段的大小,然后检查max
字段。
例子
没有使用选项的createCollection()
方法的基本语法如下 -
可以使用命令show collections
检查创建的集合。
以下示例显示了createCollection()
方法的语法,其中几个重要选项 -
在 MongoDB 中,不需要创建集合。当插入一些文档时,MongoDB 会自动创建集合。
MongoDB删除集合
drop()方法
MongoDB 的 db.collection.drop()
用于从数据库中删除集合。
语法
drop()
命令的基本语法如下 -
示例
首先,检查数据库 test
中可用的集合。
现在删除名称为 mycollection
的集合。
再次检查当前数据库的集合列表,如下 -
如果选定的集合成功删除,drop()
方法将返回true
,否则返回false
。
MongoDB数据类型
MongoDB支持许多数据类型。 其中一些是 -
- 字符串 - 这是用于存储数据的最常用的数据类型。MongoDB中的字符串必须为
UTF-8
。 - 整型 - 此类型用于存储数值。 整数可以是
32
位或64
位,具体取决于服务器。 - 布尔类型 - 此类型用于存储布尔值(
true
/false
)值。 - 双精度浮点数 - 此类型用于存储浮点值。
- 最小/最大键 - 此类型用于将值与最小和最大
BSON
元素进行比较。 - 数组 - 此类型用于将数组或列表或多个值存储到一个键中。
- 时间戳 -
ctimestamp
,当文档被修改或添加时,可以方便地进行录制。 - 对象 - 此数据类型用于嵌入式文档。
- 对象 - 此数据类型用于嵌入式文档。
- Null - 此类型用于存储
Null
值。 - 符号 - 该数据类型与字符串相同; 但是,通常保留用于使用特定符号类型的语言。
- 日期 - 此数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建日期对象并将日,月,年的日期进行指定自己需要的日期时间。
- 对象ID - 此数据类型用于存储文档的ID。
- 二进制数据 - 此数据类型用于存储二进制数据。
- 代码 - 此数据类型用于将JavaScript代码存储到文档中。
- 正则表达式 - 此数据类型用于存储正则表达式。
MongoDB插入文档
我们将学习如何在MongoDB集合中插入文档。
insert()方法
要将数据插入到 MongoDB 集合中,需要使用 MongoDB 的 insert()
或save()
方法。
语法
insert()
命令的基本语法如下:
示例
这里mycol
是集合的名称,在前一章中所创建的。如果数据库中不存在集合,则MongoDB将创建此集合,然后将文档插入到该集合中。
在插入的文档中,如果不指定_id
参数,那么 MongoDB 会为此文档分配一个唯一的ObjectId。
_id
为集合中的每个文档唯一的12
个字节的十六进制数。 12
字节划分如下 -
要在单个查询中插入多个文档,可以在insert()
命令中传递文档数组。如下所示 -
> db.mycol.insert([
{
_id: 101,
title: 'MongoDB Guide',
description: 'MongoDB is no sql database',
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: 102,
title: 'NoSQL Database',
description: "NoSQL database doesn't have tables",
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 210,
comments: [
{
user:'user1',
message: 'My first comment',
dateCreated: new Date(2017,11,10,2,35),
like: 0
}
]
},
{
_id: 104,
title: 'Python Quick Guide',
description: "Python Quick start ",
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['Python', 'database', 'NoSQL'],
likes: 30,
comments: [
{
user:'user1',
message: 'My first comment',
dateCreated: new Date(2018,11,10,2,35),
like: 590
}
]
}
])
要插入文档,也可以使用db.post.save(document)
。 如果不在文档中指定_id
,那么save()
方法将与insert()
方法一样自动分配ID的值。如果指定_id
,则将以save()
方法的形式替换包含_id
的文档的全部数据。
其它插入文档的方法
db.collection.insertOne()方法
db.collection.insertOne()
方法将单个文档插入到集合中。以下示例将新文档插入到库存集合中。 如果文档没有指定_id
字段,MongoDB会自动将_id
字段与ObjectId
值添加到新文档。
db.collection.insertOne()
方法返回包含新插入的文档的`_id```字段值的文档。
执行结果如下 -
db.collection.insertMany()方法
db.collection.insertMany()
方法将多个文档插入到集合中,可将一系列文档传递给db.collection.insertMany()
方法。以下示例将三个新文档插入到库存集合中。如果文档没有指定_id
字段,MongoDB会向每个文档添加一个ObjectId值的_id
字段。
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
{ item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
{ item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])
insertMany()
返回包含新插入的文档_id
字段值的文档。执行结果如下 -
> db.inventory.insertMany([
... { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
... { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
... { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
... ])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("59552c1c46be576f199feb56"),
ObjectId("59552c1c46be576f199feb57"),
ObjectId("59552c1c46be576f199feb58")
]
}
>
MongoDB查询文档
我们将学习如何从MongoDB集合中查询文档。
find()方法
要从MongoDB集合查询数据,需要使用MongoDB的find()
方法。
语法
find()
命令的基本语法如下:
>db.COLLECTION_NAME.find(document)
find()
方法将以非结构化的方式显示所有文档。
pretty()方法
要以格式化的方式显示结果,可以使用pretty()
方法。
语法
> db.mycol.find().pretty()
示例
>db.mycol.find().pretty()
{
"_id": 100,
"title": "MongoDB Overview",
"description": "MongoDB is no sql database",
"by": "yiibai tutorials",
"url": "http://www.yiibai.com",
"tags": ["mongodb", "database", "NoSQL"],
"likes": "100"
}
>
除了find()
方法外,还有一个findOne()
方法,它只返回一个文档。
MongoDB 与 RDBMS的等效 Where 子句
要在一些条件的基础上查询文档,可以使用以下操作。
下面我们将对上表中的所有操作演示 -
MongoDB中的AND操作符
语法
在find()
方法中,如果通过使用’,
‘将它们分开传递多个键,则 MongoDB 将其视为AND
条件。 以下是AND
的基本语法 -
示例
以下示例将显示由“yiibai tutorials
”编写并且标题为“MongoDB Overview”的所有教程。
对于上面给出的例子,等效的SQL where
子句是 -
SELECT * FROM mycol where by ='yiibai tutorials' AND title ='MongoDB Overview'
可以在find
子句中传递任意数量的键值。
MongoDB中的OR操作符
语法
在要根据OR
条件查询文档,需要使用$or
关键字。 以下是OR
条件的基本语法 -
示例
以下示例将显示由“yiibai tutorials
”编写或标题为“MongoDB Overview”的所有教程。
使用 AND 和 OR 条件一起
示例
以下示例将显示likes
大于10
以及标题是“MongoDB Overview
”或者“yiibai tutorials
”的所有文档。 等价SQL where子句为 -
SELECT * FROM mycol where likes> 10 AND(by ='yiibai tutorials' OR title ='MongoDB Overview')
查询嵌入/嵌套文档
这里演示如何使用:db.collection.find()
方法对嵌入/嵌套文档的查询操作的示例。 此页面上的示例使用inventory
集合。要填充库存(inventory
)集合以准备一些数据,请运行以下命令:
匹配嵌入/嵌套文档
要在作为嵌入/嵌套文档的字段上指定相等条件,请使用查询过滤器文档{<field>:<value>}
,其中<value>
是要匹配的文档。
例如,以下查询选择字段size
等于{ h: 14, w: 21, uom: "cm" }
的所有文档:
查询嵌套字段
要在嵌入/嵌套文档中的字段上指定查询条件,请使用点符号(“field.nestedField
”)。
在嵌套字段上指定等于匹配
以下示例选择在size
字段中嵌套的字段uom
等于“in
”的所有文档:
使用查询运算符指定匹配
查询过滤器文档可以使用查询运算符来指定,如以下形式的条件:
以下查询使用size
字段中嵌入的字段h
中的小于运算符($lt
):
指定AND条件
以下查询选择嵌套字段h
小于15
的所有文档,嵌套字段uom
等于“in
”,status
字段等于“D
”:
MongoDB更新文档
MongoDB的update()
和save()
方法用于将集合中的文档更新。update()
方法更新现有文档中的值,而save()
方法使用save()
方法中传递的文档数据替换现有文档。
MongoDB Update()方法
update()
方法更新现有文档中的值。
语法
update()
方法的基本语法如下 -
示例
考虑mycol
集合具有以下数据 -
以下示例将为标题为“MongoDB Overview
”的文档设置为“New Update MongoDB Overview
”。
默认情况下,MongoDB只会更新一个文档。要更新多个文档,需要将参数’multi
‘设置为true
。
MongoDB Save()方法
save()
方法使用save()
方法中传递的文档数据替换现有文档。
语法
MongoDB save()
方法的基本语法如下所示:
以下示例将_id
为 100
的文档使用新的文档替换。
MongoDB删除文档
我们将学习如何删除 MongoDB 集合中的文档。
remove()方法
MongoDB中的 remove()
方法用于从集合中删除文档。 remove()
方法接受两个参数。 一个是删除条件,第二个是标志:justOne
。
- criteria - (可选)符合删除条件的集合将被删除。
- justOne - (可选)如果设置为
true
或1
,则只删除一个文档。
语法
remove()
方法的基本语法如下 -
假设mycol
集合具有以下数据。
以下示例将删除_id
为“100
”的文档。
只删除一条文档记录
如果有多条记录,并且只想删除第一条记录,则在remove()
方法中设置justOne
参数。
删除所有文档记录
删除所有文档记录,可在remove()
方法中设置justOne
参数。
如果不指定删除条件,MongoDB 将删除集合中的所有文档。 这相当于SQL的truncate
命令。