使用Eggjs連接MySQL能夠使用Sequelizehtml
sequelize 是一個普遍使用的 ORM 框架,它支持 MySQL、PostgreSQL、SQLite 和 MSSQL 等多個數據源。mysql
npm install --save egg-sequelize mysql2
複製代碼
config/plugin.jsgit
sequelize: {
enable: true,
package: 'egg-sequelize',
},
複製代碼
config/config.default.jsgithub
// sequelize
config.sequelize = {
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
database: 'egg-db',
username: 'root', // 數據庫用戶名
password: '12345678', // 數據庫密碼
timezone: '+08:00', // 設置時區
define: {
timestamps: true, // 自動寫入時間戳 created_at updated_at
paranoid: true, // 字段生成軟刪除時間戳 deleted_at
underscored: true, // 全部駝峯命名格式化
},
};
複製代碼
CREATE DATABASE IF NOT EXISTS `egg-db`;
複製代碼
sequelize 提供了 sequelize-cli 工具來實現 Migrationssql
npm install --save-dev sequelize-cli
複製代碼
將全部數據庫 Migrations 相關的內容都放在 database
目錄下,在項目根目錄下新建一個 .sequelizerc
配置文件數據庫
.sequelizercnpm
'use strict';
const path = require('path');
module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'app/model'),
};
複製代碼
npx sequelize init:config
npx sequelize init:migrations
複製代碼
執行完後會生成 database/config.json
文件和 database/migrations
目錄json
修改 database/config.json
中的內容,將其改爲項目中使用的數據庫配置api
database/config.jsonbash
{
"development": {
"dialect": "mysql",
"host": "127.0.0.1",
"port": 3306,
"database": "egg-db",
"username": "root",
"password": "12345678"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
複製代碼
npx sequelize migration:generate --name=init-users
複製代碼
執行完後會在 database/migrations
目錄下生成一個 migration 文件(${timestamp}-init-users.js
)
database/migrations/202104****-init-users.js
'use strict';
module.exports = {
// 在執行數據庫升級時調用的函數,建立 users 表
up: async (queryInterface, Sequelize) => {
const { INTEGER, STRING, DATE, DECIMAL } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
user_name: {
type: STRING,
allowNull: false,
unique: true,
comment: '用戶名,惟一',
},
pass_word: STRING,
gender: {
type: DECIMAL,
allowNull: false,
defaultValue: 3,
comment: '性別(1 男性,2 女性,3 保密)',
},
birthday: DATE,
city: STRING,
picture: STRING,
created_at: DATE,
updated_at: DATE,
deleted_at: DATE,
});
},
down: async queryInterface => {
await queryInterface.dropTable('users');
},
};
複製代碼
# 升級數據庫
npx sequelize db:migrate
# 若是有問題須要回滾,能夠經過 `db:migrate:undo` 回退一個變動
# npx sequelize db:migrate:undo
# 能夠經過 `db:migrate:undo:all` 回退到初始狀態
# npx sequelize db:migrate:undo:all
複製代碼
npx sequelize migration:generate --name=init-userfollows
複製代碼
編寫Migration
database/migrations/202104****-init-Userfollow.js
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE } = Sequelize;
await queryInterface.createTable('userfollows', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
user_id: {
type: INTEGER,
allowNull: false,
comment: '用戶的 id',
},
follower_id: {
type: INTEGER,
allowNull: false,
comment: '被關注用戶的 id',
// 外鍵 用戶表ID
references: {
model: 'users',
key: 'id',
},
},
created_at: DATE,
updated_at: DATE,
deleted_at: DATE,
});
},
down: async queryInterface => {
await queryInterface.dropTable('userfollows');
},
};
複製代碼
# 升級數據庫
npx sequelize db:migrate
複製代碼
app/model/userfollow.js
'use strict';
module.exports = app => {
const { INTEGER } = app.Sequelize;
const Userfollow = app.model.define('userfollows', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
userId: INTEGER,
});
Userfollow.associate = () => {
// 一對一關係 每一個 followerId 對應一個用戶
Userfollow.belongsTo(app.model.User, {
foreignKey: 'followerId',
targetKey: 'id',
});
};
return Userfollow;
};
複製代碼
app/model/users.js
'use strict';
module.exports = app => {
const { STRING, INTEGER, DECIMAL, DATE } = app.Sequelize;
const User = app.model.define('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
userName: {
type: STRING,
allowNull: false,
unique: true,
comment: '用戶名,惟一',
},
passWord: STRING,
gender: {
type: DECIMAL,
allowNull: false,
defaultValue: 3,
comment: '性別(1 男性,2 女性,3 保密)',
},
birthday: DATE,
city: STRING,
picture: STRING,
});
User.associate = () => {
// 一對多關係 一個用戶有多個粉絲
User.hasMany(app.model.Userfollow, {
foreignKey: 'userId',
targetKey: 'followerId',
});
};
return User;
};
複製代碼
app/controller/userfollow.js
// 獲取粉絲列表
async getFans() {
const { ctx } = this;
const data = await ctx.service.userfollow.getUsersByFollower(ctx.params.id, ctx.request.query);
ctx.body = { status: true, msg: '粉絲列表獲取成功', data };
}
複製代碼
app/service/userfollow.js
// ***
const { Op } = require('sequelize');
const { toInt } = require('../extend/utils'); // toInt 將字符串轉爲數值型
// ***
async getUsersByFollower(followerId, query) {
const { pageNumber = 1, pageSize = 10 } = query;
const result = await this.ctx.model.User.findAndCountAll({
limit: toInt(pageSize),
offset: toInt(pageSize) * (toInt(pageNumber) - 1),
attributes: [ 'id', 'userName', 'picture', 'city', 'gender' ],
order: [[ 'id', 'desc' ]],
include: [
{
model: this.ctx.model.Userfollow,
attributes: [ ],
where: {
followerId,
userId: {
[ Op.ne]: followerId,
},
},
},
],
});
return result;
}
複製代碼
app/controller/userfollow.js
// 獲取關注列表
async getFollowers() {
const { ctx } = this;
const data = await ctx.service.userfollow.getFollowersByUser(ctx.params.id, ctx.request.query);
ctx.body = { status: true, msg: '關注列表獲取成功', data };
}
複製代碼
app/service/userfollow.js
async getFollowersByUser(userId, query) {
const { pageNumber = 1, pageSize = 10 } = query;
const result = await this.ctx.model.Userfollow.findAndCountAll({
limit: toInt(pageSize),
offset: toInt(pageSize) * (toInt(pageNumber) - 1),
order: [[ 'id', 'desc' ]],
attributes: [ ],
include: [
{
model: this.ctx.model.User,
attributes: [ 'id', 'userName', 'picture', 'city', 'gender' ],
},
],
where: {
userId,
followerId: {
[Op.ne]: userId,
},
},
});
return result;
}
複製代碼
app/router.js
router.get('/api/v1/user/:id/fans', controller.userfollow.getFans); // 獲取用戶的粉絲列表
router.get('/api/v1/user/:id/follow', controller.userfollow.getFollowers); // 獲取用戶的關注列表
複製代碼
// ***
複製代碼
// GET http://127.0.0.1:7001/api/v1/user/1/fans?pageNumber=1&pageSize=10
{
"status": true,
"msg": "粉絲列表獲取成功",
"data": {
"count": 2,
"rows": [
{
"id": 3,
"userName": "test3",
"picture": null,
"city": "杭州",
"gender": "1"
},
{
"id": 2,
"userName": "test2",
"picture": null,
"city": "上海",
"gender": "3"
}
]
}
}
// http://127.0.0.1:7001/api/v1/user/3/follow?pageNumber=1&pageSize=10
{
"status": true,
"msg": "關注列表獲取成功",
"data": {
"count": 1,
"rows": [
{
"user": {
"id": 1,
"userName": "test1",
"picture": null,
"city": "北京",
"gender": "3"
}
},
]
}
}
複製代碼
const result = await this.ctx.model.Userfollow.create({
userId,
followerId,
});
複製代碼
const result = await this.ctx.model.Userfollow.destroy({
where: {
userId,
followerId,
},
});
複製代碼
// ...
const user = await this.ctx.model.User.findByPk(id);
// ...
await user.update({ userName, gender, birthday, city, picture });
複製代碼
const result = await this.ctx.model.Userfollow.findOne({
where: {
userId,
followerId,
},
});
複製代碼
關於更多Sequelize的用法 訪問 www.sequelize.com.cn/
---END---