likes
comments
collection
share

PostgreSQL: 使用Node.js和Sequelize批量载入数据

作者站长头像
站长
· 阅读数 12

前言

不论你是从零开发一套系统,还是给现有的系统增添功能,你都需要与数据处理打交道。我们可能会在开发的过程中,使用mock API读取数据文件,或者使用能紧密地反应生产环境的种子数据库,我更偏向后面这种方式,因为其产生的bug更少一些

开始

假设我们要搭建提供不同课程的应用平台,那么在Node.js API层,其代码如下所示:

// server.js
const express = require("express");
const App = express();
 
const courses = [
   {title: "CSS Fundamentals", "thumbnail": "https://fake-url.com/css"}],
   {title: "JavaScript Basics", "thumbnail": "https://fake-url.com/js-basics"}],
   {title: "Intermediate JavaScript", "thumbnail": "https://fake-url.com/intermediate-js"}
];
 
App.get("/courses", (req, res) => {
   res.json({data: courses});
});
 
App.listen(3000);

当我们请求/courses,会返回代码里定义的三个课程,但真实的情况,往往更为复杂,我们如何创建更友好的后端应用呢?

使用JSON

我们在courses.js里定义所有的课程数据,然后在server.js里引用,代码如下所示:

// courses.js
 
module.exports = [
   {title: "CSS Fundamentals", "thumbnail": "https://fake-url.com/css"}],
   {title: "JavaScript Basics", "thumbnail": "https://fake-url.com/js-basics"}],
   {title: "Intermediate JavaScript", "thumbnail": "https://fake-url.com/intermediate-js"},
   ...
];
 
// server.js
 
...
const courses = require("/path/to/courses.js");
...

我们可以在返回的数据内加上分页以及大小限制,但是如何允许用户新增&编辑他们提交的课程呢?此时,我们需要数据库来存储这些数据,接下来,让我们一步步实现它

使用Sequelize批量载入JSON数据

为解决上面的问题,我们选择了PostgreSQL。我们可以本地安装使用它,或者连接它的云数据库,比如YugabyteDB Managed。它除了是高性能的分布式SQL数据库,还允许多用户共享集群。随着应用的增长,我们的数据层也需要延伸到多个节点和区域。

在创建YugabyteDB Managed账号后,我们使用Sequelize ORM创建一个免费的数据库集群

首先,我们需要在终端安装Sequelize

// terminal
> npm i sequelize

然后,我们使用Sequelize建立数据库连接,创建表,在表内存放数据

// database.js
 
// JSON-array of courses
const courses = require("/path/to/courses.js");
 
// Certificate file downloaded from YugabyteDB Managed
const cert = fs.readFileSync(CERTIFICATE_PATH).toString();
 
// Create a Sequelize instance with our database connection details
const Sequelize = require("sequelize");
const sequelize = new Sequelize("yugabyte", "admin", DB_PASSWORD, {
   host: DB_HOST,
   port: "5433",
   dialect: "postgres",
   dialectOptions: {
   ssl: {
       require: true,
       rejectUnauthorized: true,
       ca: cert,
   },
   },
   pool: {
   max: 5,
   min: 1,
   acquire: 30000,
   idle: 10000,
   }
});
 
// Defining our Course model
export const Course = sequelize.define(
   "course",
   {
       id: {
           type: DataTypes.INTEGER,
           autoIncrement: true,
           primaryKey: true,
       },
       title: {
           type: DataTypes.STRING,
       },
 
       thumbnail: {
           type: DataTypes.STRING,
       },
   }
);
 
 
async function seedDatabase() {
   try {
       // Verify that database connection is valid
       await sequelize.authenticate();
 
       // Create database tables based on the models we've defined
       // Drops existing tables if there are any
       await sequelize.sync({ force: true });
 
       // Creates course records in bulk from our JSON-array
       await Course.bulkCreate(courses);
 
       console.log("Courses created successfully!");
   } catch(e) {
       console.log(`Error in seeding database with courses: ${e}`);
   }
}
 
// Running our seeding function
seedDatabase();

通过SequelizebulkCreate方法,我们可以一次性插入多条记录,见下面代码

// JSON-array of courses
const courses = require("/path/to/courses.js");
 
async function insertCourses(){
	for(let i = 0; i < courses.length; i++) {
		await Course.create(courses[i]); 
	}
}
 
insertCourses();

数据插入需要先建立TCP三次握手连接、发送请求、解析请求数据、返回服务端数据、关闭连接等步骤。当然你们也可以通过轮询连接来优化。但是与之前的模式相比,bulkCreate可一次性插入大批量数据,且性能得到显著提升,更方便开发者维护。

现在,我们可以使用Sequelize model请求数据库,返回课程数据

// server.js
 
const express = require("express");
const App = express();
 
// Course model exported from database.js
const { Course } = require("/path/to/database.js")
 
App.get("/courses", async (req, res) => {
   try {
       const courses = await Course.findAll();
       res.json({data: courses});
   } catch(e) {
       console.log(`Error in courses endpoint: ${e}`);
   }
});
App.listen(3000);

现在我们的应用网站,不再只是一个静态数据结构的网站,而是一个功能齐全的数据库网站啦!这是不是挺简单的?

如果我们将数据存储在CSV文件(微软Excel的一种)里,那我们如何将文件数据注入到数据库内呢?

与CSVs一起工作

网络上有很多NPM包,可以将CSV文件转换为JSON,我在这里推荐csvtojson,因为它入手简单

首先安装npm

npm i csvtojson

现在我们使用它将CSV文件转换为JSON数组

// courses.csv

title,thumbnail

CSS Fundamentals,https://fake-url.com/css

JavaScript Basics,https://fake-url.com/js-basics

Intermediate JavaScript,https://fake-url.com/intermediate-js
// database.js

...

const csv = require('csvtojson');

const csvFilePath = "/path/to/courses.csv";

 

// JSON-array of courses from CSV

const courses = await csv().fromFile(csvFilePath);

...

await Course.bulkCreate(courses);

...

最后,我们可以使用Sequelize批量插入转换后的courses.csv数据