跳至主要内容

使用 MongoDB 的 NoSQL 全面教程

了解 NoSQL 数据库——为何选择 NoSQL、它与关系型数据库的差异、常见类型,并使用 MongoDB 设计您自己的 NoSQL 数据库。
· 9分钟 阅读

使用 AI 探索

随着数字时代数据量的爆炸式增长,数据库在存储、管理和分析海量数据方面至关重要。总体而言,数据库主要分为两类:SQL 和 NoSQL 数据库。

SQL 数据库使用结构化格式,数据以带有模式的表格形式组织。与 SQL 数据库不同,NoSQL 数据库提供灵活的模式,能够存储半结构化和非结构化数据。它们为管理并利用当今数字环境中产生的海量数据提供了必要的基础设施。

本综合指南将讲解 NoSQL 数据库的基本原理,以及业界可用的不同类型的 NoSQL 数据库及其示例。在掌握这些基础后,我们将深入介绍流行的 NoSQL 数据库 MongoDB,并学习如何执行 CRUD(创建、读取、更新和删除)操作。

什么是 NoSQL?

NoSQL 的全称是“Not Only SQL(不止是 SQL)”,它的诞生旨在解决关系型数据库的局限。关系型数据库遵循严格的结构,采用表格形式,并使用 SQL(结构化查询语言)进行数据操作。

NoSQL 数据库为存储半结构化和非结构化数据提供了更灵活的方法。

NoSQL 数据库的关键优势在于适合处理结构各异的大规模数据。NoSQL 数据库是无模式的,使其具备更高的敏捷性和可扩展性。

不过,这些优势也伴随着权衡。它们在一致性方面较弱,对复杂查询的支持也有限。尽管存在这些限制,它们仍因其带来的益处而被广泛使用,并与 SQL 数据库形成互补。

您可以阅读这篇关于 SQL 与 NoSQL 数据库关键差异的文章,并从单独的教程中了解在何种情况下应选择哪一种的建议。

NoSQL 数据库的类型

为满足不同用例的需求,NoSQL 数据库采用多种数据模型来组织和访问数据。以下是四种常见的 NoSQL 数据库类型。

  1. 键值对是最简单的 NoSQL 数据库形式。数据以键和值的配对形式存储,并可通过键进行检索。示例包括 Redis 和 Amazon DynamoDB。
  2. 列式数据库按列而非按行组织数据。这种结构在按列检索数据时效率很高。Apache Cassandra、HBase 和 Google Bigtable 属于列式数据库。
  3. 图数据库以由节点、边和属性组成的图结构来存储数据。Neo4j 和 Amazon Neptune 是常见的图数据库。
  4. 文档型以类 JSON 的文档形式存储数据。文档结构可变,甚至可以包含嵌套数据。这类数据库应用广泛,示例包括 MongoDB 和 CouchDB。

如需进一步了解不同类型的数据库,建议参考我们的教程:NoSQL 数据库:每位数据科学家都需要知道的内容。

在了解了什么是 NoSQL 以及 NoSQL 数据库的类型之后,现在是进行 NoSQL 数据库动手实践的时候了。

NoSQL 教程:为博客平台设计 NoSQL 数据库

通过一个贴近实际的示例来理解并动手尝试我们所讲的概念至关重要。让我们一起完成一个 NoSQL 教程。

假设您想要搭建自己的博客平台。您希望创建博文、允许评论并进行更新。由于您知道数据是非结构化的,因此会意识到 MongoDB 等 NoSQL 数据库适合当前用例。

MongoDB 是一个开源的 NoSQL 数据库。它不使用表格,而是以类 JSON 的文档形式存储数据。这便于表示复杂的结构和关系。管理不同的数据类型(包括文本、数字或图片)也很方便,这些类型在博客中很常见。

让我们先在您的机器上安装并配置 MongoDB。

1. 安装与配置 MongoDB

安装 MongoDB 十分简单。我们可以从MongoDB 官方网站下载并安装。不同操作系统的步骤有所差异,请在其官方文档中查看适用于您操作系统的安装说明。

安装完成后,启动 MongoDB。根据您的操作系统,打开终端并输入以下命令:

// Linux
sudo systemctl start mongod

//Mac OS
brew services start [email protected]

我们会看到类似“Successfully started”的输出,如下所示。

Output: Starting MongoDB

输出:正在启动 MongoDB。(本文及下方所有图片均由作者提供)

MongoDB 安装包包含名为 mongosh 的 MongoDB Shell,我们可以用它与 MongoDB 数据库交互,因此无需额外安装。

在终端中运行以下命令启动 MongoDB Shell:

mongosh

执行 mongosh 命令后,将出现如下输出,表示已连接到您的数据库。

Start the MongoDB shell

启动 MongoDB Shell。

完成 MongoDB 的安装后,我们将继续定义数据模型。

2. 定义数据模型

我们将创建名为“blog”的数据库,以及名为“posts”和“comments”的两个集合。“posts”集合用于存储博文条目,“comments”集合用于存储这些博文的评论。

每个帖子文档包含标题、内容、作者和创建日期等字段;每条评论文档包含评论内容、作者以及关联的帖子 ID 等字段。

要列出所有现有数据库,请在 Shell 中执行 show dbs。如果这是您首次使用 MongoDB,您将看到如下输出。

列出现有数据库。

默认情况下,我们会使用 test 数据库。尽管我们身处 test 数据库,但在向其中的集合插入文档之前,数据库并不会被真正创建。

要创建新数据库,请执行 use <database_name>。

在本示例中,我们将“blog”作为数据库名称。请执行 use blog 来创建新数据库。正如上文所述,在我们向数据库中插入集合之前,执行 show dbs 命令不会显示新数据库。因此,请执行以下命令创建集合。

// create database
use blog

// create collection
db.createCollection("posts")
db.createCollection("comments")

执行 use blog 将把当前数据库从“test”切换为“blog”。

输出:创建数据库与集合。

创建集合后,我们可以通过 show dbs 命令进行验证。

数据库列表。

我们已成功创建数据库和集合。

3. 实现 CRUD 操作

MongoDB 支持四种与数据交互的主要 CRUD(创建、读取、更新、删除)操作:

  1. 创建:要在 MongoDB 中创建文档,可使用 insertOne() 或 insertMany() 方法将其插入集合。文档可以包含任意合法的 JSON 数据,从而实现灵活的模式设计。
  2. 读取:要从 MongoDB 读取数据,可使用 find() 方法进行查询。查询会根据指定条件筛选文档并返回结果。
  3. 更新:要更新文档,可使用 updateOne() 或 updateMany()。这些方法可实现灵活的数据修改。
  4. 删除:要从集合中删除文档,可使用 deleteOne() 或 deleteMany() 方法。删除是基于指定条件执行的,例如匹配某个字段的值。

既然已经了解了这些命令,让我们在博客这一用例中将其付诸实践。

4. 创建博文

在 MongoDB 数据库中插入文档有两种方法。

  1. insertOne():一次插入一个文档
  2. insertMany():一次插入多个文档

让我们使用这两种方法向数据库添加博文。以下代码在“posts”集合中创建文档。每个文档包含标题、内容、作者和创建日期。

// use insertOne() method to insert one document to the "posts" collection
db.posts.insertOne({
   title: "Introduction to NoSQL with MongoDB",
   content: "MongoDB is a NoSQL database that stores data in JSON format",
   author: "Arunn Thevapalan",
   createdAt: new Date()
})

// array of blog post documents
var postsData = [
   {
       title: "Getting Started with MongoDB",
       content: "Learn the basics of MongoDB",
       author: "Arunn Thevapalan",
       createdAt: new Date()
   },
   {
       title: "Advanced MongoDB Techniques",
       content: "Explore advanced features of MongoDB",
       author: "Jim Murphy",
       createdAt: new Date()
   }
];

// use insertMany() to insert multiple documents
db.posts.insertMany(postsData);

该输出表示 MongoDB 服务器已成功接收并处理 insertOne 请求。

输出:向集合插入一条文档。

同样,下面的输出表示 insertMany 请求已成功处理。

输出:向集合插入多条文档。

了解了创建操作后,接下来是读取操作。

5. 查询博文

我们可以使用 find() 方法从集合中检索数据。要从“posts”集合中检索上述博文,请执行以下命令。

db.posts.find()

find 方法将检索“posts”集合中的所有文档。下面的输出展示了我们在上一步插入的所有文档。

输出:从集合检索文档。

6. 为帖子添加评论

假设我们要为一篇帖子添加几条评论,可以向“comments”集合插入文档。评论与博文相关联,因此我们会保留帖子 ID 的引用。

// use an object id from any of the above entries
var postId = ObjectId("664bfc27f74ef93812b2179e")

// insert one comment
db.comments.insertOne({
   postId: postId,
   content: "Informative article!",
   author: "Anne Smith",
   createdAt: new Date()
})

该输出表示 MongoDB 服务器已接收并处理请求。

输出:创建引用其他文档的文档。

7. 查询某帖子的评论

要检索与特定博文关联的评论,可以在 find() 方法中使用查询过滤条件:

// retrieve the above comment

db.comments.find({postId: postId})

下面的输出显示了我们在上一步插入的评论。

输出:使用 find 查询查找文档。

用户创建博文后,往往希望能在之后进行更新。接下来,让我们看看如何更新现有文档。

8. 更新博文

与插入类似,更新也可以单条进行或批量进行。

  1. updateOne():一次更新一个文档
  2. updateMany():一次更新多个文档

尝试将博文“Introduction to NoSQL with MongoDB”的标题修改为“Absolute Beginner Guide to NoSQL with MongoDB”。

由于我们在之前的步骤中知道该帖子的 ID,请执行以下代码来更改标题。请确保将 postId 更新为您的文档 ID。

var postId = ObjectId("664bfc27f74ef93812b2179e");

db.posts.updateOne(
   { _id: postId },
   { $set: { title: "Absolute Beginner guide to NoSQL with MongoDB"} }
);

// verify update
db.posts.find({_id: postId})

输出表明请求已成功处理。共找到 1 条匹配文档,并修改了 1 条文档。

输出:更新文档。

9. 删除博文

要删除一篇博文,可以使用 deleteOne()。同前述操作类似,也可以选择使用 deleteMany() 一次删除多条文档。

var postId = ObjectId("664bfc27f74ef93812b2179e");

// delete post
db.posts.deleteOne({ _id: postId });

// verify deletion -> no output
db.posts.find({_id: postId})

该输出确认删除已成功。

Output: Delete a document from a collection

输出:从集合中删除文档

当然,我们对博客平台的设计做了简化。实际平台通常更复杂,还会包含高亮、点赞、鼓掌、推荐等各种操作。但这些操作都基于 CRUD 中的一种,我们现在已经很好地掌握了这些底层概念。接下来就轮到您基于这些操作去探索并尝试更多功能了。

总结

本教程向您介绍了 NoSQL 数据库。我们从基本概念入手,讲解了 NoSQL 数据库的定义、它与关系型数据库的区别以及其类型。

随后我们进一步扩展至 MongoDB 这一广泛使用的文档型数据库。最后,我们通过一个简单示例,为博客平台设计了数据库并进行了实操。

在为新的用例设计数据库时遇到困难很正常,我们鼓励您参考官方文档以了解最新的函数和示例。

如果您渴望拓展对 NoSQL 的认识,以下是一些更深入的课程与教程:

Arunn Thevapalan

作者

Arunn Thevapalan

作为一名高级数据科学家,我设计、开发并部署大规模机器学习解决方案,帮助企业做出更明智的数据驱动决策。作为数据科学写作者,我分享所学心得、职业建议以及深入的实践型教程。

主题