关于mongodb:MongoDB-Mongoose与Nodejs结合使用的后端开发的最佳实践

38次阅读

共计 3454 个字符,预计需要花费 9 分钟才能阅读完成。

MongoDB 无疑是当今最受欢迎的 NoSQL 数据库抉择之一,它有一个很棒的社区和生态系统。

在本文中,咱们将介绍在应用 Node.js 设置 MongoDB 和 Mongoose 时应遵循的一些最佳实际。

1. 为什么须要 Mongoose?

为了了解咱们为什么须要 Mongoose,咱们先来理解 MongoDB(也是一个数据库)在架构层面的工作原理。

  • 你有一个数据库服务器(例如 MongoDB 社区服务器)
  • 你正在运行一个 Node.js 脚本(作为一个过程)

MongoDB 服务器在 TCP 套接字上监听(通常),你的 Node.js 过程能够应用 TCP 连贯来连贯它。

然而在 TCP 之上,MongoDB 也有本人的协定来理解客户端(咱们的 Node.js 过程)到底想要数据库做什么。

对于这种通信,咱们不须要学习咱们在 TCP 层上要发送的音讯,而是借助一个“驱动”软件将其形象掉,在这里称为 MongoDB 驱动。MongoDB 驱动在这里以 npm 包的模式提供。

当初请记住,MongoDB 驱动程序负责连贯和形象你的低层通信申请 / 响应——但作为开发者,这只能让你走到这一步。

因为 MongoDB 是一个无模式数据库,它为你提供了比初学者所需的更多的性能。更大的权力意味着更大的出错可能性,你须要缩小可在代码中制作的谬误和毁坏表的可能性。

Mongoose 是对原生 MongoDB 驱动(我下面提到的 npm 包)的一个形象。

抽象化的个别教训法令(我了解的形式)是,每一个抽象化都会损失一些底层操作能力。但这并不一定意味着它是坏的,有时它能进步生产力 1000 倍以上,因为你基本不须要齐全拜访底层 API。

一个好的思路是,你在技术上用 C 语言和 Python 创立一个实时聊天利用。作为开发人员,Python 的例子将更容易和更快地实现,生产率更高。C 可能更有效率,但它会在生产力、开发速度、谬误、解体方面付出微小的代价。另外,在大多数状况下,你不须要领有 C 给你的能力来实现 websockets。

同样,应用 Mongoose,你能够限度你的底层 API 拜访的范畴,但能够开释出很多潜在的收益和良好的 DX。

2. 如何连贯 Mongoose + MongoDB

首先,让咱们疾速看看在 2020 年应该如何用 Mongoose 连贯到你的 MongoDB 数据库。

mongoose.connect(DB_CONNECTION_STRING, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
    useFindAndModify: false
})

这种连贯格局确保你正在应用 Mongoose 的新 URL 解析器,而且你没有应用任何废除的做法。

3. 如何执行 Mongoose 操作

当初咱们先来疾速讨论一下 Mongoose 的操作,以及你应该如何执行这些操作。

Mongoose 为您提供以下两种抉择:

  1. 基于游标的 (Cursor-based) 查问
  2. 全程检索 (Full fetching) 查问

3.1 基于游标的 (Cursor-based) 查问

基于游标的查问是指一次只解决一条记录,同时一次从数据库中获取一条或一批文档。这是一种在无限的内存环境下解决海量数据的无效形式。

设想一下,你要在 1GB/ 1 核云服务器上解析总大小为 10GB 的文档。你不能获取整个汇合,因为那在你的零碎中不适合。游标是一个很好的(也是惟一的)抉择。

3.2 全程检索 (Full fetching) 查问

这是一种查问类型,你能够一次性取得查问的全副响应。在大多数状况下,这就是你要应用的办法。因而,咱们将在这里次要关注这个办法。

4. 如何应用 Mongoose 模型(Models)

模型是 Mongoose 的超级力量,它们帮忙你执行“schema”规定,并为你的 Node 代码提供无缝集成到数据库调用中。

第一步是定义一个好的模型:

import mongoose from 'mongoose'

const CompletedSchema = new mongoose.Schema(
    {type: { type: String, enum: ['course', 'classroom'], required: true },
        parentslug: {type: String, required: true},
        slug: {type: String, required: true},
        userid: {type: String, required: true}
    },
    {collection: 'completed'}
)

CompletedSchema.index({slug: 1, userid: 1}, {unique: true})

const model = mongoose.model('Completed', CompletedSchema)
export default model

这是一个间接从 codedamn 的代码库中删减的例子。这里有一些乏味的事件你应该留神。

  1. 在所有须要的字段中,尽量放弃 required: true。如果你在创建对象时没有应用 TypeScript 这样的动态类型查看零碎来帮助你正确地查看属性名,那么这能够为你省去很多麻烦。另外,收费的验证也超级酷。
  2. 定义索引和惟一字段。unique 属性也能够在模式中增加。索引是一个很宽泛的话题,所以我在这里就不深究了。但从大范畴来看,它们的确能够帮忙你放慢很多查问速度。
  3. 明确定义一个汇合名。尽管 Mongoose 能够依据模型的名称主动给出一个汇合名称(例如这里的 Completed here),但在我看来这太形象了。你至多应该晓得你的数据库名称和代码库中的汇合。
  4. 如果能够,请应用枚举来限度值。

5. 如何执行 CRUD 操作

CRUD 是指创立、读取、更新和删除。这是四个根本选项,有了这四个选项,你就能够在数据库中进行任何模式的数据操作。让咱们疾速看看这些操作的一些例子。

5.1 Create

这简略来说就是在数据库中创立一条新记录。让咱们应用咱们下面定义的模型来创立一条记录。

try {const res = await CompletedSchema.create(record)
} catch(error) {console.error(error)
    // handle the error
}

同样,这里有一些提醒:

  1. 应用 async-await 而不是回调(看起来不错,但没有突破性的性能劣势)
  2. 在查问四周应用 try-catch 块,因为你的查问可能会因为一些起因而失败(重复记录、谬误的值等)。

5.2 Read

这意味着从数据库中读取现有的值。这听起来很简略,但你应该晓得 Mongoose 的几个小问题。

const res = await CompletedSchema.find(info).lean()
  1. 你能看到那里的 lean() 函数调用吗?它对性能超级有用。默认状况下,Mongoose 会解决从数据库中返回的文档,并在其上增加其 神奇 的办法(例如 .save)。
  2. 当你应用 .lean() 时,Mongoose 会返回一般的 JSON 对象,而不是内存和资源惨重的文档。使查问速度更快,对 CPU 的耗费也更小。
  3. 然而,如果你的确想要更新数据,你能够省略 .lean() (咱们接下来会看到)

5.3 Update

如果你曾经有了一个 Mongoose 文档(没有应用 .lean() 触发),你能够简略地去批改对象属性,而后用 object.save() 保留它。

const doc = await CompletedSchema.findOne(info)
doc.slug = 'something-else'
await doc.save()

记住,这里有两个数据库调用。第一个是在 findOne 上,第二个是在 doc.save 上。

如果能够,你应该总是缩小拜访数据库的申请数量(因为如果比拟内存、网络和磁盘,网络简直总是最慢的)。

在另一种状况下,能够应用如下查问:

const res = await CompletedSchema.updateOne(<condition>, <query>).lean()

并且只会对数据库进行一次调用。

5.4 Delete

应用 Mongoose 删除也很简略,让咱们看看如何删除单个文档:

const res = await CompletedSchema.deleteOne(<condition>)

updateOne 一样 deleteOne 也承受第一个参数作为文档的匹配条件。

还有另一个办法叫 deleteMany,只有当你晓得要删除多个文档时才应用。

在任何其余状况下,总是应用 deleteOne 来防止意外的屡次删除,特地是当你试图本人执行查问时。

正文完
 0