ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Sequelize 教程 > 原文: [http://zetcode.com/javascript/sequelize/](http://zetcode.com/javascript/sequelize/) Sequelize 教程展示了如何使用 Sequelize ORM 在 JavaScript 中对数据库进行编程。 ## Sequelize Sequelize 是 Node.js 的基于 Promise 的 ORM。 它可与 PostgreSQL,MySQL,SQLite 和 MSSQL 方言配合使用,并具有可靠的事务支持,关系,读取复制等功能。 对象关系映射(ORM)是一种从面向对象的语言访问关系数据库的技术。 在本教程中,我们使用 MySQL。 ## 设置续集 我们初始化一个 Node 应用并安装 Sequelize 和 MySQL 适配器。 ```js $ nodejs -v v10.12.0 ``` 我们使用 Node 版本 10.12.0。 ```js $ npm init ``` 我们启动一个新的 Node 应用。 ```js $ npm i sequelize $ nmp i mysql2 ``` 我们安装 Seqelize 和 MySQL 驱动程序。 有两个驱动程序可用:`mysql`和`mysql2`; 我们选择了后者。 ## Sequelize 认证 在第一个示例中,我们创建与 MySQL 数据库的连接。 `authenticate.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/testdb'; const sequelize = new Sequelize(path, { operatorsAliases: false }); sequelize.authenticate().then(() => { console.log('Connection established successfully.'); }).catch(err => { console.error('Unable to connect to the database:', err); }).finally(() => { sequelize.close(); }); ``` 该示例在连接到 MySQL 数据库时显示一条消息。 ```js const Sequelize = require('sequelize'); ``` 我们加载 Sequelize 模块。 ```js const path = 'mysql://user12:12user@localhost:3306/testdb'; ``` 这是 MySQL 连接路径。 它包含用户名,密码,主机名,数据库端口和数据库名称。 ```js const sequelize = new Sequelize(path, { operatorsAliases: false }); ``` 我们实例化 Sequelize。 ```js sequelize.authenticate().then(() => { console.log('Connection established successfully.'); ... ``` `authenticate()`方法通过尝试向数据库进行认证来测试连接。 建立连接后,我们将打印一条消息。 ```js }).catch(err => { console.error('Unable to connect to the database:', err); ... ``` 如果发生错误,我们将打印一条错误消息。 ```js }).finally(() => { sequelize.close(); }); ``` 最后,我们关闭数据库连接。 ```js $ node authenticate.js Executing (default): SELECT 1+1 AS result Connection established successfully ``` 这是输出。 输出也包括调试输出。 ## Sequelize 模型定义 `Model`代表数据库中的表。 此类的实例代表数据库行。 Sequelize 的`define()`方法定义了一个新模型。 `define_model.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false }); let Dummy = sequelize.define('dummy', { description: Sequelize.STRING }); Dummy.sync().then(() => { console.log('New table created'); }).finally(() => { sequelize.close(); }) ``` 该示例创建一个简单的模型。 它将模型保存到数据库表中。 ```js let Dummy = sequelize.define('dummy', { description: Sequelize.STRING }); ``` 创建了一个新模型`Dummy`。 第一个参数是型号名称。 第二个参数由属性组成,这些属性是表列。 在我们的例子中,我们有一个列名`description`,它是`String`类型。 ```js Dummy.sync().then(() => { console.log('New table created'); }).finally(() => { sequelize.close(); }) ``` `sync()`方法将模型同步到数据库。 实际上,它将创建一个新的`dummies`表。 (表名是复数的。) ```js $ node model_define.js Executing (default): CREATE TABLE IF NOT EXISTS `dummies` (`id` INTEGER NOT NULL auto_increment , `description` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB; Executing (default): SHOW INDEX FROM `dummies` New table created ``` 这是输出。 默认情况下,Sequelize 提供日志记录。 可以使用`logging`选项将其关闭。 ```js mysql> describe dummies; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | description | varchar(255) | YES | | NULL | | | createdAt | datetime | NO | | NULL | | | updatedAt | datetime | NO | | NULL | | +-------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) ``` 我们检查在 MySQL 中创建的表。 Sequelize 还创建了另外两个列:`createdAt`和`updatedAt`。 可以使用`timestamps`选项将其关闭。 ## Sequelize 删除表 用`drop()`方法删除一个表。 `drop_table.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Dummy = sequelize.define('dummy', { description: Sequelize.STRING }); Dummy.drop().then(() => { console.log('table deleted'); }).finally(() => { sequelize.close(); }); ``` 该示例删除`dummies`表。 ## Sequelize 时间戳 Sequelize 自动为模型添加时间戳。 我们可以使用`timestamps`控制此行为。 `timestamps.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false, define: { timestamps: false } }); let Dummy = sequelize.define('dummy', { description: Sequelize.STRING }); sequelize.sync({force: true}).then(() => { Dummy.create({ description: 'test 1' }).then(() => { console.log('table created'); }).finally(() => { sequelize.close(); }); }); ``` 该示例创建一个没有时间戳的表。 ```js const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false, define: { timestamps: false } }); ``` 在这里,我们关闭时间戳记。 ```js mysql> describe dummies; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | description | varchar(255) | YES | | NULL | | +-------------+--------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) ``` 我们确认表中没有时间戳。 ## Sequelize 批量创建 `bulkCreate()`方法创建并批量插入多个实例。 该方法采用对象数组。 `bulk_create_notes.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); let notes = [ { description: 'Tai chi in the morning' }, { description: 'Visited friend' }, { description: 'Went to cinema' }, { description: 'Listened to music' }, { description: 'Watched TV all day' }, { description: 'Walked for a hour' }, ]; sequelize.sync({ force: true }).then(() => { Note.bulkCreate(notes, { validate: true }).then(() => { console.log('notes created'); }).catch((err) => { console.log('failed to create notes'); console.log(err); }).finally(() => { sequelize.close(); }); }); ``` 表格示例记录了几行。 ```js const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); ``` 我们禁用日志记录。 ```js sequelize.sync({ force: true }).then(() => { ``` `sqeuelize.syn()`同步所有型号。 在`force`选项丢弃的表,如果它的创建之前就存在。 ```js Note.bulkCreate(notes, { validate: true }).then(() => { console.log('notes created'); ... ``` `bulkCreate()`创建具有六行的表格。 ```js mysql> select * from notes; +----+------------------------+---------------------+---------------------+ | id | description | createdAt | updatedAt | +----+------------------------+---------------------+---------------------+ | 1 | Tai chi in the morning | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | | 2 | Visited friend | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | | 3 | Went to cinema | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | | 4 | Listened to music | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | | 5 | Watched TV all day | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | | 6 | Walked for a hour | 2018-10-21 14:34:28 | 2018-10-21 14:34:28 | +----+------------------------+---------------------+---------------------+ 6 rows in set (0.00 sec) ``` 这是在数据库中创建的表。 ## Sequelize `build()`和`save()` 使用`build()`和`save()`分两步或使用`create()`一步创建新行。 `build_save.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); const note = Note.build({ description: 'Took a cold bath' }); note.save().then(() => { console.log('new task saved'); }).finally(() => { sequelize.close(); }); ``` 本示例使用`build()`和`save()`创建一个新的笔记。 ## Sequelize `findById` 使用`findById()`,我们通过其 ID 查找特定行。 `find_by_id.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); Note.findById(2).then((note) => { console.log(note.get({ plain: true })); console.log('********************') console.log(`id: ${note.id}, description: ${note.description}`); }).finally(() => { sequelize.close(); }); ``` 该示例查找带有 ID 2 的笔记。 ```js console.log(note.get({ plain: true })); ``` 默认情况下,Sequelize 返回大量元数据。 要关闭数据,我们使用`plain: true`选项。 ```js $ node find_by_id.js { id: 2, description: 'Visited friend', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z } ******************** id: 2, description: Visited friend ``` 我们将行打印两次。 在第一种情况下,我们返回所有数据。 在第二种情况下,我们仅选择两个字段。 ## Sequelize `findOne` `findOne()`方法搜索单个行。 `find_one.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); Note.findOne({ where: { id: 1 } }).then(note => { console.log(note.get({ plain: true })); }).finally(() => { sequelize.close(); }); ``` 该示例使用`find_one()`返回表的第一行。 `where`选项指定要查找的 ID。 ```js $ node find_one.js { id: 1, description: 'Tai chi in the morning', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z } ``` 这是输出。 ## Sequelize `async`和`await` 在下一个示例中,我们使用`async`和`await`关键字。 `find_one2.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getOneNote() { let user = await Note.findOne(); console.log(user.get('description')); sequelize.close(); } getOneNote(); ``` 我们使用`async`和`await`关键字返回带有`findOne()`的第一行。 ## Sequelize 计数 `count()`方法计算表中的行数。 `count_rows.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function countRows() { let n = await Note.count(); console.log(`There are ${n} rows`); sequelize.close(); } countRows(); ``` 该示例计算`notes`表中的行数。 ```js $ node count_rows.js There are 7 rows ``` 目前,表格中有 7 行。 ## Sequelize 删除行 使用`destroy()`方法删除一行。 它返回已删除的行数。 `delete_row.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function deleteRow() { let n = await Note.destroy({ where: { id: 2 } }); console.log(`number of deleted rows: ${n}`); sequelize.close(); } deleteRow(); ``` 该示例删除 ID 为 2 的行。 ## Sequelize 更新行 用`update()`方法更新一行。 `update_row.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function updateRow() { let id = await Note.update( { description: 'Finished reading history book' }, { where: { id: 1 } }); sequelize.close(); } updateRow(); ``` 该示例更新了第一行的描述。 ## Sequelize `findAll` `findAll()`方法搜索多个实例。 `find_all.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function findAllRows() { let notes = await Note.findAll({ raw: true }); console.log(notes); sequelize.close(); } findAllRows(); ``` 该示例使用`findAll()`从数据库表中检索所有行。 ```js let notes = await Note.findAll({ raw: true }); ``` `raw: true`选项关闭元数据。 ```js $ node find_all.js [ { id: 1, description: 'Finished reading history book', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T16:00:22.000Z }, { id: 2, description: 'Visited friend', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z }, { id: 3, description: 'Went to cinema', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z }, { id: 4, description: 'Listened to music', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z }, { id: 5, description: 'Watched TV all day', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z }, { id: 6, description: 'Walked for a hour', createdAt: 2018-10-21T14:34:28.000Z, updatedAt: 2018-10-21T14:34:28.000Z }, { id: 7, description: 'Took a cold bath', createdAt: 2018-10-21T14:49:51.000Z, updatedAt: 2018-10-21T14:49:51.000Z } ] ``` 该示例返回了七行。 ## Seqelize 选择列 使用`attributes`选项,我们可以选择要包括在查询中的列。 `columns.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getTwoColumns() { let notes = await Note.findAll({ attributes: ['id', 'description'], raw: true }); console.log(notes); sequelize.close(); } getTwoColumns(); ``` 在示例中,我们选择`id`和`description`列。 ```js $ node columns.js Executing (default): SELECT `id`, `description` FROM `notes` AS `notes`; [ { id: 1, description: 'Finished reading history book' }, { id: 3, description: 'Went to cinema' }, { id: 4, description: 'Listened to music' }, { id: 5, description: 'Watched TV all day' }, { id: 6, description: 'Walked for a hour' } ] ``` 这是输出。 ## Seqelize `offset`和`limit` 使用`offset`和`limit`属性,我们可以定义`findAll()`方法中要包括的行的初始跳过和行数。 `offset_limit.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getRows() { let notes = await Note.findAll({ offset: 2, limit: 3, attributes: ['id', 'description'], raw: true }); console.log(notes); sequelize.close(); } getRows(); ``` 该示例从第二行开始还原三行。 ```js $ node offset_limit.js [ { id: 3, description: 'Went to cinema' }, { id: 4, description: 'Listened to music' }, { id: 5, description: 'Watched TV all day' } ] ``` 这是输出。 ## Seqelize 顺序排序 为了在查询中包含`ORDER BY`子句,我们使用`order`选项。 `order_by.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getRows() { let notes = await Note.findAll({ order: [['description', 'DESC']], attributes: ['id', 'description'], raw: true }) console.log(notes); sequelize.close(); } getRows(); ``` 在示例中,我们从表中选择所有行,并按描述以降序对其进行排序。 ```js $ node order_by.js Executing (default): SELECT `id`, `description` FROM `notes` AS `notes` ORDER BY `notes`.`description` DESC; [ { id: 3, description: 'Went to cinema'}, { id: 5, description: 'Watched TV all day' }, { id: 6, description: 'Walked for a hour'}, { id: 2, description: 'Visited friend' }, { id: 1, description: 'Tai chi in the morning' }, { id: 4, description: 'Listened to music' } ] ``` 从输出中我们可以看到`ORDER BY`子句已添加到查询中。 ## Seqelize `Op.IN`运算符 使用`Op.IN`运算符,我们可以确定指定的值是否与子查询或列表中的任何值匹配。 `operator_in.js` ```js const Sequelize = require('sequelize'); const Op = Sequelize.Op; const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getRows() { let notes = await Note.findAll({ where: { id: { [Op.in]: [3, 6] } } }); notes.forEach(note => { console.log(`${note.id}: ${note.description}`); }); sequelize.close(); } getRows(); ``` 在示例中,我们选择与 ID 列表匹配的所有行。 ```js $ node operator_in.js 3: Went to cinema 6: Walked for a hour ``` 输出显示两行:ID 为 3 和 6。 ## Seqelize `Op.between`运算符 使用`Op.between`运算符,我们可以确定指定值是否与给定范围内的任何值匹配。 `operator_between.js` ```js const Sequelize = require('sequelize'); const Op = Sequelize.Op; const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Note = sequelize.define('notes', { description: Sequelize.STRING }); async function getRows() { let notes = await Note.findAll({ where: { id: { [Op.between]: [3, 6] } }}); notes.forEach(note => { console.log(`${note.id}: ${note.description}`); }); sequelize.close(); } getRows(); ``` 该示例使用`Op.between`运算符显示行`3..6`。 ## Sequelize `belongsTo` Sequelize `belongsTo`在源模型和提供的目标模型之间创建一对一的关联。 外键添加在源上。 `belongs_to.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Employee = sequelize.define('employees', { name: Sequelize.STRING }); let Project = sequelize.define('projects', { name: Sequelize.STRING }); Employee.belongsTo(Project); let employees = [ { name: 'Jane Brown' }, { name: 'Lucia Benner' }, { name: 'Peter Novak' } ]; sequelize.sync({ force: true }).then(() => { return Employee.bulkCreate(employees); }).then((employees) => { let works = []; let i = 0; employees.forEach(employee => { let pname = 'Project ' + String.fromCharCode('A'.charCodeAt() + i); i++; let work = Project.create({ name: pname }).then(project => { employee.setProject(project); }); works.push(work); }); Promise.all(works).then(() => sequelize.close()); console.log('finish'); }); ``` 在示例中,我们有两个模型:`Employee`和`Project`。 我们使用`belongsTo`在两个模型之间创建一对一关联。 我们将数据添加到模型中。 ```js let Employee = sequelize.define('employees', { name: Sequelize.STRING }); let Project = sequelize.define('projects', { name: Sequelize.STRING }); ``` 我们定义了两个模型。 ```js Employee.belongsTo(Project); ``` 我们在`Employee`和`Project`模型之间创建一对一关联。 外键在`Employee`中生成。 ```js let employees = [ { name: 'Jane Brown' }, { name: 'Lucia Benner' }, { name: 'Peter Novak' } ]; ``` 我们将创建三名员工。 ```js let works = []; ``` `works`数组用于存储生成的`Promise`。 ```js employees.forEach(employee => { let pname = 'Project ' + String.fromCharCode('A'.charCodeAt() + i); i++; let work = Project.create({ name: pname }).then(project => { employee.setProject(project); }); works.push(work); }); ``` 我们遍历所有员工,并为每个员工生成一个新项目。 `setProject()`添加了一个新项目。 `Project.create()`生成一个新的`Promise`,将其添加到`works`数组中。 ```js Promise.all(works).then(() => sequelize.close()); ``` `Promise.all()`解析数组中的所有`promise`。 接下来,我们检索联接的数据。 当我们生成还从其他表中获取关联数据的查询时,我们会渴望加载。 通过`include`选项启用了预先加载。 `belongs_to2.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Employee = sequelize.define('employees', { name: Sequelize.STRING }); let Project = sequelize.define('projects', { name: Sequelize.STRING }); Employee.belongsTo(Project); Employee.findAll({include: [Project]}).then(employees => { employees.forEach(employee => { console.log(`${employee.name} is in project ${employee.project.name}`); }); }).finally(() => { sequelize.close(); }); ``` 该示例列出了员工及其项目。 ```js Employee.findAll({include: [Project]}).then(employees => { ``` 在查询中,我们添加`include`选项,其中包括关联的模型。 ```js $ node belongs_to2.js Jane Brown is in project Project A Lucia Benner is in project Project B Peter Novak is in project Project C ``` 这是输出。 ## 双向化一对一关系 双向关系在两个方向上均有效。 我们可以从源模型引用目标模型,反之亦然。 为了在模型之间创建双向一对一关系,我们将其与`belongsTo()`和`hasOne()`映射。 `bidi_one2one.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let Employee = sequelize.define('employees', { name: Sequelize.STRING }); let Project = sequelize.define('projects', { name: Sequelize.STRING }); Employee.belongsTo(Project); Project.hasOne(Employee); Project.findAll({include: [Employee]}).then(projects => { projects.forEach(project => { console.log(`${project.name} belongs to user ${project.employee.name}`); }); }).finally(() => { sequelize.close(); }); ``` 在此示例中,我们从每个项目中检索一名员工。 ```js Employee.belongsTo(Project); Project.hasOne(Employee); ``` 为了实现双向关联,我们还使用`hasOne()`映射了模型。 ```js $ node bidi_one2one.js Project A belongs to user Jane Brown Project B belongs to user Lucia Benner Project C belongs to user Peter Novak ``` 这是输出。 ## Sequelize `hasMany` Sequelize `hasMany`在源和提供的目标之间创建多对一关联。 外键添加到目标上。 `one_to_many.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let User = sequelize.define('user', { name: Sequelize.STRING, }); let Task = sequelize.define('task', { description: Sequelize.STRING, }); User.hasMany(Task); async function createTables() { await User.sync(); await Task.sync(); console.log('done'); sequelize.close(); } createTables(); ``` 首先,我们创建两个表:`users`和`tasks`。 在第二步中,我们用数据填充表。 `one_to_many2.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let User = sequelize.define('user', { name: Sequelize.STRING }); let Task = sequelize.define('task', { description: Sequelize.STRING, }); User.hasMany(Task); let mytasks1 = [ { description: 'write memo' }, { description: 'check accounts' } ]; let mytasks2 = [ { description: 'make two phone calls' }, { description: 'read new emails' }, { description: 'arrange meeting' } ]; async function addUsersTasks() { let user1 = await User.create({ name: 'John Doe' }); let tasks1 = await Task.bulkCreate(mytasks1); await user1.setTasks(tasks1); let user2 = await User.create({ name: 'Debbie Griffin' }); let tasks2 = await Task.bulkCreate(mytasks2); await user2.setTasks(tasks2); console.log('done'); sequelize.close(); } addUsersTasks(); ``` 我们有两个执行某些任务的用户。 ```js let user1 = await User.create({ name: 'John Doe' }); ``` 使用`User.create()`创建一个新用户。 ```js let tasks1 = await Task.bulkCreate(mytasks1); ``` 使用`Task.bulkCreate()`生成新任务。 ```js await user1.setTasks(tasks1); ``` 使用`setTasks()`将任务添加到用户。 最后,我们检索数据。 `one_to_many3.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let User = sequelize.define('user', { name: Sequelize.STRING }); let Task = sequelize.define('task', { description: Sequelize.STRING, }); User.hasMany(Task); async function showUsersTasks() { let users = await User.findAll({ include: [Task] }); users.forEach(user => { console.log(`${user.name} has tasks: `); let tasks = user.tasks; tasks.forEach(task => { console.log(` * ${task.description}`); }) }); console.log('done'); sequelize.close(); } showUsersTasks(); ``` 在示例中,我们显示了所有用户及其关联的任务。 ```js let users = await User.findAll({ include: [Task] }); ``` 要启用紧急加载,我们使用`include`选项。 急切的加载是在查询中也检索关联的数据时。 ```js $ node one_to_many3.js John Doe has tasks: * write memo * check accountsDebbie Griffin has tasks: * make two phone calls * read new emails * arrange meeting done ``` 这是输出。 ## 双向一对多关系 双向一对多关系在两个方向上均有效。 为了在模型之间建立双向的一对多关系,我们使用`hasMany()`和`belongsTo()`映射它们。 `bidi_one2many.js` ```js const Sequelize = require('sequelize'); const path = 'mysql://user12:12user@localhost:3306/mydb'; const sequelize = new Sequelize(path, { operatorsAliases: false, logging: false }); let User = sequelize.define('user', { name: Sequelize.STRING }); let Task = sequelize.define('task', { description: Sequelize.STRING }); User.hasMany(Task); Task.belongsTo(User); async function showTaskUser() { let task = await Task.findOne({ include: [User] }); console.log(`${task.description} belongs to ${task.user.name}`); sequelize.close(); } showTaskUser(); ``` 该示例从检索的任务中获取用户。 ```js User.hasMany(Task); Task.belongsTo(User); ``` 为了实现双向一对一关系,我们使用`hasMany()`和`belongsTo()`映射模型。 ```js $ node bidi_one2many.js write memo belongs to John Doe ``` 这是输出。 在本教程中,我们使用了`Seqeulize`库。 我们创建了一些与 MySQL 交互的命令行程序。 您可能也对以下相关教程感兴趣: [Knex.js 教程](/javascript/knex/), [Node Postgres 教程](/javascript/nodepostgres/), [Lodash 教程](/javascript/lodash/),[书架教程](/javascript/bookshelf/), 或列出[所有 JavaScript 教程](/all/#js)。