最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • MongoDB + Mongoose与Node.js结合使用的后端开发的最佳实践

    正文概述 掘金(杭州程序员张张)   2020-12-21   738

    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 来避免意外的多次删除,特别是当你试图自己执行查询时。


    原文:www.freecodecamp.org
    翻译:blog.zhangbing.site


    起源地下载网 » MongoDB + Mongoose与Node.js结合使用的后端开发的最佳实践

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元