网络埋伏纪事

Node Hero - 5. Node.js 数据库教程

网络埋伏纪事 · 2016-11-21翻译 · 1423阅读 原文链接

如下的 Node.js 数据库教程将展示如何设置 Node.js 应用程序的数据库,并且教你使用它的基础知识。

将数据存储在一个全局变量中

正如在上章所学,为用户提供静态页面,可能适合着陆页或者个人博客。但是,如果想交付个性化的内容,就必须将数据存在某个地方。

举个例子:用户注册。可以为个别用户提供定制内容,或者只让它在用户通过身份验证后可用。

如果用户想注册你的应用程序,你可能想创建一个路由处理器来让他注册成功:

const users = []

app.post('/users', function (req, res) {  
    // 从请求消息体中获取用户发送的数据
    const user = req.body
    users.push({
      name: user.name,
      age: user.age
    })
    res.send('注册成功!')
})

通过这种方式,可以把用户存储在一个全局变量中,这个全局变量在应用程序生命周期都会驻留在内存中。

使用这种方式会因为几个原因而带来问题:

  • 内存很贵,
  • 每次重新启动应用程序时,内存都会重置,
  • 如果不清理的话,有时候会遇到栈溢出。

将数据存储在文件中

出现在你脑海中的下一件事情可能是将数据存储在文件中。

如果把用户数据永久性地存储在文件系统中,就可以避免之前列出的问题。

实践中,这个方法看起来就像如下这样:

const fs = require('fs')

app.post('/users', function (req, res) {  
    const user = req.body
    fs.appendToFile('users.txt', JSON.stringify({ name: user.name, age: user.age }), (err) => {
        res.send('注册成功!')
    })
})

这种方式我们不会丢失用户数据,即使服务器重启后也不会。这种解决方案也是经济有效的,因为买存储空间比买内存更便宜。

不幸的是,用这种方式存储用户数据依然有几个缺陷:

  • 添加用户数据是可以的,但是想想更新或者删除。
  • 如果是存到文件,并行访问文件就没那么容易了(系统级锁会阻止写数据)。
  • 当扩展应用程序时,没法把文件分割放在服务器之间(可以,但是方法超出了本教程的等级)。

这就是真实数据库起作用的地方。

你可能已经听说过数据库有两种主要类型:SQL 和 NOSQL。

SQL

我们以 SQL 开始。SQL 是一种设计用于关系型数据库的查询语言。根据正在使用的产品,SQL 有几种风格,但基本原理都是相同。

数据本身会被存储在表中,每个插入的块将会被表示为表中的一行,就像 Google Sheets 或者 Microsoft Excel 中的一样。

在一个 SQL 数据库中,你可以定义 schema - 这些 schema 会为你要放进去的数据提供一个骨架。在存储数据之前,必须设置不同值的类型。例如,必须为用户数据定义一个表,必须告诉数据库用户名是字符串类型,年龄是整型。

NoSQL

另一方面,NoSQL 数据库在最近十年变得相当流行。如果使用 NoSQL,就不需要定义 schema,可以存储任意 JSON。这对 JavaScript 很方便,因为在 JavaScript 中将对象转换为 JSON 很容易。不过,使用 NoSQL 要当心,因为它无法保证数据的一致性,也无法知道数据库中存的是什么。

Node.js 和 MongoDB

我们总会听到对 Node.js 的一个常见误解:

"Node.js 只能用 MongoDB( MongoDB 是最流行的 NoSQL 数据库)。"

根据我的经验,这是不正确的。大多数数据库都有驱动程序可以用,它们在 NPM 上也有库。据我看,它们与 MongoDB 一样简单易用。

Node.js 和 PostgreSQL

为简单起见,我们打算在下面的示例中使用 SQL。我选择的是 PostgreSQL。

要让 PostgreSQL 启动和运行,必须将它安装到你的电脑上。如果是 Mac,就用 homebrew 安装 PostgreSQL。另外,如果是 Linux,就用你用的包管理器安装它。

Node.js Database Example PostgreSQL

进一步的信息请阅读这篇优秀的指南,让你的第一个数据库启动和运行起来。

如果你打算用一种数据库浏览工具,我推荐使用命令行程序 psql - 它与 PostgreSQL 服务器安装程序绑在一起。这里有一个小速查表,如果你开始用 PostgreSQL,这玩意迟早会派上用场。

如果不喜欢命令行界面,可以用开源的 PostgreSQL 管理图形界面工具 pgAdmin

注意,SQL 本身就是一门语言,我们不会讲解它所有功能,只会提及最简单的。要了解更多的关于 SQL 的知识,这里有不少讲解 PostgreSQL 基础知识的课程都还不错。

Node.js 数据库交互

首先,得创建要使用的数据库。为此,在终端中键入如下命令:

createdb node_hero

然后,创建用户表:

CREATE TABLE users(  
  name VARCHAR(20),
  age SMALLINT
);

最后,回到编码。如下是通过 Node.js 程序与数据交互的代码:

'use strict'

const pg = require('pg')  
const conString = 'postgres://username:password@localhost/node_hero' // 确保要匹配你自己数据库的凭据

pg.connect(conString, function (err, client, done) {  
  if (err) {
    return console.error('error fetching client from pool', err)
  }
  client.query('SELECT $1::varchar AS my_first_query', ['node hero'], function (err, result) {
    done()

    if (err) {
      return console.error('error happened during query', err)
    }
    console.log(result.rows[0])
    process.exit(0)
  })
})

这是一个简单的 PostgreSQL 'hello world' 示例。注意第一个参数是 SQL 命令字符串,第二个参数是给查询提供的参数值数组。

如果就按用户输入插入到数据库,会有很大的安全问题。这种方式可以防止 SQL 注入式攻击,这种类型的攻击是攻击者试图利用完全未处理的 SQL 查询。在创建任何面向用户的应用程序时,必须总要考虑这种情况。要学习更多关于 SQL 安全性的知识,请查看我们的 Node.js 应用程序安全备忘录

下面继续前一示例。

app.post('/users', function (req, res, next) {  
  const user = req.body

  pg.connect(conString, function (err, client, done) {
    if (err) {
      // 将错误传递给 express 错误处理器
      return next(err)
    }
    client.query('INSERT INTO users (name, age) VALUES ($1, $2);', [user.name, user.age], function (err, result) {
      done() //这个 done 回调会通知 pg 驱动程序连接可以被关闭,或者返回给连接缓冲池

      if (err) {
        // 将错误传递给 express 错误处理器
        return next(err)
      }

      res.send(200)
    })
  })
})

完成解锁:用户存储在数据库中!:) 现在我们试着获取他们。下一步,为用户获取给应用程序添加一个新的端点。

app.get('/users', function (req, res, next) {  
  pg.connect(conString, function (err, client, done) {
    if (err) {
      // 将错误传递给 express 错误处理器
      return next(err)
    }
    client.query('SELECT name, age FROM users;', [], function (err, result) {
      done()

      if (err) {
        // 将错误传递给 express 错误处理器
        return next(err)
      }

      res.json(result.rows)
    })
  })
})

也不算很难,对吧?

现在你可以运行提供给 Node.js 应用程序的任何复杂 SQL 查询。

使用这种技术,你可以将数据永久存储在应用程序中,多亏了 Node-postgreSQL 模块团队的辛勤劳动,使存储数据变得易如反掌。

我们已经完成了在 Nodejs 中使用数据库所必须知道的所有基础知识。现在自己去创建一些东西好了。

尝试、实验,因为这是称为一个真正的 Node 勇士的最佳方式。实践并准备下一章如果与第三方 API 通讯!

如果你有任何有本教程相关的或者与在 Node.js 中使用数据库的问题,只管提出来!

相关文章