MongoDB 简介






4.88/5 (24投票s)
MongoDB 简介
引言
我在某个地方读到,MongoDB 是面向现代 Web 的数据库,这让我思考,这个大家都在谈论的新数据库到底有什么特别之处。相信我,当我开始深入研究时,我真的印象深刻。所以,本文献给伟大的 MongoDB。在本文中,我们将学习 MongoDB 的基础知识。我已尽力让内容更易于理解。我希望在阅读完本文后,您能对 MongoDB 有足够的了解。
什么是 MongoDB?
MongoDB 是一个开源的面向文档的数据库。MongoDB 属于 NoSQL(非关系型)数据库类别,这意味着它不像关系型数据库那样遵循固定的模式结构。
MongoDB 不能取代关系型数据库,但应将其视为一种替代方案。MongoDB 可以安装在 Windows、Linux 和 MAC 上,因此它是一个跨平台数据库。它不支持 JOIN 操作,但可以表示丰富、层次化的数据结构。我最喜欢的功能之一是它易于扩展且性能高。
MongoDB 数据库由一组数据库组成,每个数据库包含多个集合。MongoDB 是无模式的,这意味着每个集合可以包含不同类型的对象。每个对象也称为文档,表示为 JSON(JavaScript 对象表示法)结构:键值对列表。值可以是三种类型:基本值、文档数组或再次是键值对列表。
让我们看看 RDBMS 和 MongoDB 有何不同
入门:安装 MongoDB
让我们在 Windows 上安装 MongoDB,以深入了解 MongoDB 的世界。请注意,本文仅介绍在 Windows 上安装 MongoDB 的步骤。
以下是安装和运行 MongoDB 的步骤
- 访问 MongoDB 官方网站(https://mongodb.ac.cn/downloads),下载最新版本的 MongoDB。如果您的 Windows 系统是 64 位,则下载 64 位版本,否则下载 32 位版本。
注意:MongoDB 的 32 位版本支持小于 2GB 的数据库,因此仅适用于测试和评估目的。
- 运行下载的安装程序 (.msi)。
- 按照安装向导中的说明进行操作。
- 默认情况下,MongoDB 将安装在 C: 驱动器中。
- 在 C: 驱动器中创建一个名为data的目录,然后在 data 目录中创建另一个名为 db 的目录。所有数据库都存储在这里。
- 在环境变量中设置 MongoDB 的路径(C:\Program Files\MongoDB\Server\3.0\bin)。
如果您按照以上步骤操作,您的 MongoDB 已经启动并运行,可以创建我们的数据库和集合了。
面向文档的数据模型
但在我们进入创建自己的数据库的下一步之前,让我们看看面向文档的数据模型到底是什么
MongoDB 中的典型文档看起来像这样
{ _id: ObjectID('4bd9e8e17cefd644108961bb'), name:'Vivek', class : '12th', subjects: [ 'physics', 'chemistry', 'math', 'english', 'computer'], address: { house_no: '12B', block: 'B', sector: 12, city : 'noida', }, grade: [ { exam: 'unit test 1', score: '60%' }, { exam: 'unit test 2', score: '70%' } ] }
上面的文档包含学生的信息,以键值对的形式。它包含记录的唯一 _id、姓名及其值、班级及其值、科目及其值(以数组形式)、地址(以另一个内嵌文档形式)以及成绩(以文档数组形式)。
如果我们必须在关系型数据库中表示相同的记录,我们将需要至少三个表。一个用于存储基本信息,如 _id、姓名、班级、地址;另一个用于存储科目;另一个用于存储成绩等。但在 MongoDB 中,我们将整个关系信息存储在一个完整的文档中,这就是我们如何弥补 MongoDB 中 JOIN 和约束的不足。在 MongoDB 中,我们没有 JOIN,但如何设计模式来管理关系取决于我们开发者。
我希望这能为您提供面向文档数据模型的基本概念。让我们看看如何在 MongoDB 中执行 CRUD 操作。
深入 MongoDB Shell
如果您已成功安装并设置了 MongoDB 的环境变量,那么您就可以开始使用 MongoDB 了。
打开 Windows 命令提示符,输入“mongod”以启动 MongoDB 服务器。MongoDB 服务器将启动,您将在屏幕底部看到“waiting for connections”消息,并且光标会闪烁,这表示您的服务器已启动并正在等待来自 MongoDB 客户端的连接。
现在打开另一个命令提示符,输入“mongo”以连接到服务器。请记住,不要关闭第一个命令提示符。
Mongo 服务器
Mongo 客户端
正如您在 Mongo 客户端中看到的那样,您将看到一些重要信息
MongoDB shell 版本:3.0.6(可能因您的 MongoDB 版本而异)
正在连接到:test(这是 MongoDB 自动为您创建并连接到的测试数据库。)
我们将在此 Shell 中编写所有查询和命令。MongoDB Shell 是一个交互式的 JavaScript 解释器,这意味着如果您了解 JavaScript,那么编写 MongoDB 命令/查询将是一件轻而易举的事情。
在 MongoDB Shell 中输入“help”并按 Enter 键,您将看到 MongoDB 为我们提供的一系列帮助函数。
好了,我们已经谈了很多,现在是时候付诸行动了,让我们来看一些命令。
- show dbs:显示系统中的数据库。
- show collections:显示数据库中的集合。
db.help()
:显示 db 方法的帮助。db.mycoll.help()
:显示集合方法的帮助。
创建我们自己的数据库
键入 use [数据库名称] 并按 Enter 键。如果数据库存在,MongoDB 将切换到该数据库;否则,它将为您创建一个全新的数据库。
例如:键入 'use students' 来创建一个名为 students 的数据库。
CRUD 操作
我们已经创建了数据库,现在是时候创建我们的集合了。那么,我们如何创建集合呢?这非常容易,只需使用 insert 命令。我给您看。
db.mycol.insert({name:'vikas'})
这里 mycol 是集合的名称,我们向其中插入了一个文档。我们只需要写集合的名称并在其中插入记录,MongoDB 将自动创建集合(如果尚未创建),否则会将记录插入到现有集合中。
因此,对于CRUD(创建、读取、更新、删除)操作,我们在 MongoDB 中有以下命令
Insert()
Insert 命令用于在集合中插入文档。如我们所知,MongoDB 中的文档存储 JSON 对象作为文档,因此 insert 命令接受 JSON 对象作为参数。
doc={ name:'xyx', class:'12th', subjects:['physics','chemisrty','maths','english','computer'], address:{ house_no:'123', sector:'50', city:'noida' } } db.mycol.insert(doc);
这里我们创建了一个名为 doc 的对象,并将其作为参数用于 insert 命令。
您也可以在不创建任何变量的情况下插入文档,并直接将文档传递到 insert 命令中,请参见下面的示例。
db.mycol.insert({ name:'Vivek', class : '12th', subjects: [ 'physics', 'chemistry', 'math', 'english', 'computer'], address: { house_no: '12B', block: 'B', sector: 12, city : 'noida', }, grade: [ { exam: 'unit test 1', score: '60%' }, { exam: 'unit test 2', score: '70%' } ] });
如果您键入命令 db.my.col.find()
,您将看到迄今为止插入的所有记录。注意,如果您键入 db.my.col.find().pretty()
,输出将是缩进良好且格式化的。
这里需要注意的一点是,我们没有为任何上述文档提供 _id,但 MongoDB 本身插入了唯一的 _id,如下所示:
"_id" : ObjectId("560f767315f507b3c0bae3f5")
当我们向 MongoDB 插入文档时,服务器要求所有传入的文档都有一个唯一的标识字段,实际上它使用 _id 来标识。文档中的 _id 字段是主键,这意味着它要求 _id 字段的值必须唯一。_id 字段是不可变的,这意味着您不能更改它。ObjectId 是一种生成唯一键的类型,它包含当前时间、构造 ObjectId 的机器的标识符、构造 ObjectId 的进程的进程 ID 以及全局于构造 ObjectId 的对象的计数器。通过将这些信息组合在一起,MongoDB 为我们创建了一个唯一的 ID。当然,我们可以创建自己的 _id 字段,但对于每个其他文档,它都必须是唯一的。
因此,我们已经看到了如何在 MongoDB 中插入文档,这意味着我们完成了 CRUD 操作的 C 部分,让我们进入下一部分。
Find()
要使用 find()
命令查询我们的集合,我们需要更多记录来查看 find() 命令的各种形式,所以让我们在集合中插入更多记录。我使用了以下命令一次性插入了 100 条记录。
for(i=0;i<100;i++) { subjects=['chemistry','physics','maths','english','computer']; for(j=0;j<5;j++) { db.marks.insert({ name:"student"+ i, subject:subjects[j], marks:Math.round(Math.random()*100) } ); } }
注意:我使用了缩进来使代码更易读,但当您在 MongoDB Shell 中编写以上代码时,请删除所有制表符和空格。
现在我们有一个名为 marks 的集合,其中包含 100 条记录。
我们之前也使用过 find()
命令,但我没有解释它是如何工作的,所以让我们看看它是如何工作的。Find 命令接受一个模式匹配参数来匹配相应的记录,就像 SQL 中 SELECT 查询的 where 子句一样。如果您在 SQL 中键入 SELECT * FROM Table,它将为您提供表中的所有记录;同样,如果您键入 db.CollectionName.find()
,它将返回集合中的所有记录。
在 find()
方法中传递参数
- 假设我们想查找
student0
的所有记录,我们将编写:db.marks.find({name:'student0'})
- 在科目为 computer 的
student0
中查找记录db.marks.find({name:'student0',subject:'computer'}).pretty()
在这里,我们传递了两个条件来匹配我们的文档,即姓名应等于 student0,科目应等于 computer。
- 查找科目为 computer 且分数大于 50 的所有学生的记录
db.marks.find({subject:'computer',marks:{$gt:50}}).pretty()
find 命令接受一个对象作为参数,同样,我们将传递一个文档来匹配条件,即分数应大于 50。
大于:$gt
大于等于:$gte
小于:$lt
小于等于:$lte
- 查找科目为 computer 且分数大于 50 且小于等于 90 的所有学生的记录
db.marks.find({subject:'computer',marks:{$gt:50,$lte:90}}).pretty()
- 查找科目为 computer 或 physics 且分数大于 90 的所有学生的记录
db.marks.find({$or:[{subject:'computer'},{subject:'physics'}],marks:{$gt:90}})
$or 接受一个需要匹配的标准数组。
- 在我们之前的 mycol 集合中,文档具有不同的模式设计,所以假设我们想查找 class 字段存在的记录
db.mycol.find({class:{$exists:true}})
类似地,我们可以写
$exists
: false 来查找 class 字段不存在的记录。 - 假设我们有一个名为
additionalsubject
的新集合db.additionalsubject.insert({name:'student1',subject:['arts','music']}) db.additionalsubject.insert({name:'student2',subject:['sports','arts']}) db.additionalsubject.insert({name:'student3',subject:['sports','cooking','music']}) db.additionalsubject.insert({name:'student4',subject:['arts','craft','music']})
并且我们想查找那些注册了 arts 的学生记录。那么查询将写为:
db.additionalsubject.find({subject:'arts'}
)但是,如果我们想查找同时注册了 arts 和 music 的学生记录,那么我们的查询将是:
db.additionalsubject.find({subject:{$all:['arts','music']}})
这里需要注意的重要一点是,
$all
将查找数组中传递的所有值,而不管它们在集合中出现的顺序。 - 类似地,我们有
$in
来查找其中传递的任何一个值。假设我们想查找注册了 sports 或 arts 的学生记录。那么查询将是:db.additionalsubject.find({subject:{$in:['sports','arts']}})
- 我们有点表示法来查询包含嵌套文档的集合。
例如,在前面显示的第一个文档中,grades 包含文档数组,如果我们想查找 exam unit test 1 的分数,那么查询将写为:
db.mycol.find({'grade.exam':'unit test 1'})
Update()
Update 命令接受两个参数,第一个是匹配条件,第二个是更新值。语法:db.[collectionName].update({matching criteria},{updated value});
MongoDB 中的 Update 命令执行四项主要任务。
- 执行批量替换,意味着它将替换整个文档,但 ObjectId 除外。例如,在我们的 additionalsubject 集合中,如果我们想更改 student1 的科目,如果我们这样写:
db.additionalsubject.update({name:'student1'},{subject:['craft']})
它不仅会更改 subject 字段,还会替换整个文档。
更新文档后
现在没有 name 字段,只有 ObjectId 和 subject 字段。所以我们可以说这不是更新文档的正确方法,因为以这种方式更新将用新的更新值替换整个文档,但当您想用新字段和新值替换旧文档时,此命令很有用。
- 仅修改所需的字段,如果我们只想修改字段的一些值,那么我们有 $set 操作符。例如:假设我们想将 student2 的姓名更改为‘xyz’,在这种情况下,我们只想修改 name 字段,而不触及其他字段,所以我们将这样写:
db.additionalsubject.update({name:'student2'},{$set:{name:'xyz'}})
更新前
更新后
- 移除不必要的字段,意味着我们可以从文档中移除我们不需要的字段,为此我们有
$unset
操作符。例如,假设我们想为姓名为‘xyz’的学生移除 subject 字段。
db.additionalsubject.update({name:'xyz'},{$unset:{subject:1}})
更新前
更新后
- Update 命令搜索与参数中指定的条件匹配的记录,如果找到记录,则更新它,否则不进行更新。我们有一个特殊的 upsert 操作符,它创建新记录然后更新它。所以如果我们尝试更新 student5 的记录,将不会发生任何事情,因为我们没有 student5 记录,但如果我们使用 upsert,那么 student5 的新记录将被创建并更新。
db.additionalsubject.update({name:'student5'},{$set:{subject:['music']}},{upsert:true})
- 如果我们想更新文档中的数组,我们可以在 MongoDB 中轻松做到这一点。我们还拥有 MongoDB 中的一些特殊操作符来更新文档中的数组。让我们看一些更新文档中数组的示例。
- 将
student3
的科目从 sports 更改为 artsdb.additionalsubject.update({name:'student3'},{$set:{'subject.0':'arts'}});
subject 是一个数组,所以如果我们想更改索引为第 0 位(0th place)的科目,我们将写
subject.0
- 向
student3
记录添加一个额外的科目。为此,我们有 $pushdb.additionalsubject.update({name:'student3'},{$push:{'subject':'sports'}})
它将在 subject 字段的末尾添加另一个科目‘sports’。
- 类似地,我们有
$pop
来从数组中移除一个值。但它将移除数组中最右边的值。$pop : 1 (remove rightmost value) $pop : -1 (remove leftmost value) db.additionalsubject.update({name:'student3'},{$pop:{'subject':1}});
- 我们有
$pushAll
来向数组添加一个或多个值。类似地,我们使用$pull
来从数组中移除一个指定的值,以及 $pullAll 来移除一个或多个值。让我们看一个例子。db.additionalsubject.update({name:'student3'},{$pushAll:{'subject':['sports','craft']}}) db.additionalsubject.update({name:'student3'},{$pullAll:{'subject':['sports','craft']}})
- 将
- MongoDB 只更新一条满足匹配条件的文档,但如果您想一次更新所有文档,我们必须传递一个附加参数 mult:true。
例如,如果我们想为
additionalsubject
集合的所有文档添加另一个附加字段:db.additionalsubject.update({},{$set:{'class':’12th’}},{multi:true})
它将向集合中的每个文档添加一个新字段 class。
因此,我们完成了 update 命令。
Remove()
Remove 命令用于从集合中移除记录,它的工作方式与 find 命令相同,它需要一个参数,即文档的匹配条件。
- 如果我们要移除姓名为
student3
的记录,我们将编写:db.additionalsubject.remove({name:'student3'})
- 如果我们想移除一个集合的所有文档,那么我们必须将一个空文档作为参数传递给 remove 命令。
db.additionalsubject.remove({})
它将移除集合中的所有文档。
结论
我们使用 MongoDB 创建了数据库,然后创建了集合,并学习了集合上的 CRUD 操作。我希望您喜欢这篇文章。当您开始使用 MongoDB 时,您将意识到其真正的强大之处。