Node.js後端開發系列之sequelize零基礎快速入門實戰

🎇🎇🎇新年快樂🎇🎇🎇

2020 鼠你最帥, 鼠你最強, 鼠你最棒, 鼠你最紅, 鼠你最美, 鼠年吉祥node

問與答

❓:你能學到什麼?
🙋:sequelize-cli的使用以及sequelize的基礎操做。mysql

❓:爲何要使用sequelize-cli?
🙋:就像你使用Git/SVN來管理源代碼的更改同樣,你可使用遷移來跟蹤數據庫的更改。git

❓:爲何不將數據模型設計好再演示?
🙋:本文講的是使用sequelize-cli和sequelize開發的過程。github

❓:怎麼會有這麼多的代碼?
🙋:每一步的代碼我都貼了出來,只要按照流程作就能快速的完成一個示例。眼見爲實,我相信這樣學習的效果更好。sql

❓:怎麼沒有事務、做用域、數據類型等知識點?
🙋:這篇是入門教程,不過學會了這篇,事務、做用域理解起來更容易。數據庫

❓:爲何沒有源代碼?
🙋:作一遍必定比看一遍的效果好。npm

準備工做

一、初始化項目json

cd 工程目錄 
 npm init -y
複製代碼

二、安裝模塊bash

npm i koa koa-body koa-router mysql2 sequelize sequelize-cli -S
複製代碼

三、添加server.js文件app

const Koa = require('koa');
 const router = require('koa-router')();
 const koaBody = require('koa-body');
 const app = new Koa();
 app.use(koaBody());

 app.use(router.routes())
    .use(router.allowedMethods('*'));

 app.listen(3000, () => {
     console.log('server is listening on 3000...')
 });
複製代碼

快速入門

一、新建.sequelizerc文件

const path = require('path');
 module.exports = {
   'config': path.resolve('config', 'config.json'), //數據庫鏈接配置文件
   'models-path': path.resolve('db', 'models'),     //模型文件
   'seeders-path': path.resolve('db', 'seeders'),   //種子文件
   'migrations-path': path.resolve('db', 'migrations') //遷移文件
 }
複製代碼

二、初始化

npx sequelize-cli init
複製代碼

三、編輯./db/config.js

"development": {
    "username": "username",
    "password": "password",
    "database": "school", //數據庫名稱
    "host": "127.0.0.1",
    "dialect": "mysql",
    "timezone": "+08:00" //設置時區爲'東八區'
  }
複製代碼

四、建立數據庫

npx sequelize-cli db:create
複製代碼

五、生成student模型文件以及遷移文件

npx sequelize-cli model:generate --name student --attributes student_name:string,student_age:integer,student_sex:boolean
複製代碼

六、編輯./db/migrations/xxxxx-create-student.js

'use strict';
 module.exports = {
   up: (queryInterface, Sequelize) => {
     return queryInterface.createTable('student', {
       id: {
         allowNull: false,
         autoIncrement: true,
         primaryKey: true,
         type: Sequelize.INTEGER
       },
       student_name: {
         type: Sequelize.STRING(10),
         allowNull:false 
       },
       student_age: {
         type: Sequelize.INTEGER,
         allowNull:false
       },
       student_sex: {
         type: Sequelize.BOOLEAN,
         allowNull:false
       }
     });
   },
   down: (queryInterface, Sequelize) => {
     return queryInterface.dropTable('student');
   }
};
複製代碼

打開xxxxx-create-student.你會發現createTable方法的第一個參數爲students,這是因爲sequelize會默認將表名稱轉換爲複數形式,這裏我將其修改成student,後面全部表名或模型名稱都會使用單數形式。

七、生成名稱爲student的數據表

npx sequelize-cli db:migrate
複製代碼

八、生成student表種子文件

npx sequelize-cli seed:generate --name init-student
複製代碼

九、編輯./db/seeders/xxxxx-init-student.js文件

'use strict';

 module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('student', [{
      student_name: '孫悟空',
      student_age: 20,
      student_sex: 1
    },{
      student_name: '白骨精',
      student_age: 18,
      student_sex: 0
    },{
      student_name: '豬八戒',
      student_age: 16,
      student_sex: 1
    }])
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('student', null, {});
  }
};
複製代碼

十、student表初始化數據

npx sequelize-cli db:seed:all
複製代碼

十一、編輯.db/models/student.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const student = sequelize.define('student', {
    student_name: DataTypes.STRING,
    student_age: DataTypes.INTEGER,
    student_sex: DataTypes.BOOLEAN,
    class_id:DataTypes.INTEGER
  }, {
    timestamps: false,//不自動添加時間字段(updatedAt,createdAt)
    freezeTableName: true,// 使用模型名稱的單數形式
    underscored: true //列名添加下劃線
  });
  student.associate = function(models) {};
  return student;
};
複製代碼

十二、編輯server.js文件

.....
 const Student  = require('./db/models').student;
 //添加學生信息
 router.post('/student', async ctx => {
     ctx.body = await Student.create(ctx.request.body);
 });
 //更新學生信息
 router.put('/student', async ctx => {
    const { id } = ctx.request.body;
    ctx.body = await Student.update(ctx.request.body, { where: { id } });
 });
 //獲取學生列表
 router.get('/students', async ctx => {
    ctx.body = await Student.findAll();
 });
 //根據id刪除學生信息
 router.delete('/student/:id', async ctx => {
    const { id } = ctx.params;
    ctx.body = await Student.destroy({ where: { id } });
});
.....
複製代碼

1三、啓動服務並使用Postman測試

node server.js
複製代碼

模型關連

hasMany(一對多)

一個班級裏面能夠有多個學生,班級與學生的關係就是一對多。爲了完成這個例子咱們會作如下幾件事情:

  1. 建立名稱爲_class的班級表
  2. _class班級表初始化數據
  3. student表添加列名爲class_id的列
  4. 從新初始化student表數據
  5. 查詢某個班級全部學生

讓咱們開始吧!

一、生成**_class**模型以及遷移文件

npx sequelize-cli model:generate --name _class --attributes class_name:string
複製代碼

二、修改./db/migrations/xxxxx-create-class.js

'use strict';
 module.exports = {
   up: (queryInterface, Sequelize) => {
     return queryInterface.createTable('_class', {
       id: {
         allowNull: false,
         autoIncrement: true,
          primaryKey: true,
         type: Sequelize.INTEGER
       },
       class_name: {
         type: Sequelize.STRING(10),
          allowNull:false
       }
     });
   },
   down: (queryInterface, Sequelize) => {
     return queryInterface.dropTable('_class');
   }
 };
複製代碼

三、生成**_class**表

npx sequelize-cli db:migrate
複製代碼

四、生成**_class**表種子文件

npx sequelize-cli seed:generate --name init-class
複製代碼

五、編輯./db/seeders/xxxxx-init-class.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('_class', [{
      class_name: '一班'
    }, {
      class_name: '二班'
    }, {
      class_name: '三班'
    }]);
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('_class', null, {});
  }
};
複製代碼

六、_class表初始化數據

npx sequelize-cli db:seed  --seed  xxxxx-init-class.js
複製代碼

七、生成修改studnet表的遷移文件

npx sequelize-cli migration:generate  --name add-column-class_id-to-student.js
複製代碼

八、編輯./db/migrations/xxxxx-add-column-class_id-to-student.js

'use strict';

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn('student', 'class_id', {
      type: Sequelize.INTEGER,
      allowNull:false
    })
  },

  down: (queryInterface, Sequelize) => {
     queryInterface.removeColumn('student', 'class_id', {});
  }
};
複製代碼

九、修改student

npx sequelize-cli db:migrate
複製代碼

十、從新生成student表種子文件

npx sequelize-cli seed:generate --name init-student-after-add-column-class_id
複製代碼

十一、編輯./db/seeders/xxxxx-init-student-after-add-column-class_id.js文件

'use strict';

 module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('student', [{
      student_name: '孫悟空',
      student_age: 20,
      student_sex: 1,
      class_id: 1
    }, {
      student_name: '白骨精',
      student_age: 18,
      student_sex: 0,
      class_id: 1
    }, {
      student_name: '豬八戒',
      student_age: 16,
      student_sex: 1,
      class_id: 2
    }, {
      student_name: '唐僧',
      student_age: 22,
      student_sex: 1,
      class_id: 1
    }, {
      student_name: '沙和尚',
      student_age: 25,
      student_sex: 1,
      class_id: 1
    }, {
      student_name: '紅孩兒',
      student_age: 13,
      student_sex: 1,
      class_id: 2
    }, {
      student_name: '黑熊怪',
      student_age: 26,
      student_sex: 1,
      class_id: 2
    }, {
      student_name: '太白金星',
      student_age: 66,
      student_sex: 1,
      class_id: 3
    }, {
      student_name: '嫦娥',
      student_age: 18,
      student_sex: 0,
      class_id: 3
    }])
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('student', null, {});
  }
};
複製代碼

十二、撤銷student表中已有的數據

npx sequelize-cli db:seed:undo --seed xxxxx-init-student.js
複製代碼

1三、stuent表從新初始化數據

npx sequelize-cli db:seed --seed  xxxxx-init-student-after-add-column-class_id.js
複製代碼

1四、編輯./db/models/_class.js文件

'use strict';
module.exports = (sequelize, DataTypes) => {
  const _class = sequelize.define('_class', {
    class_name: DataTypes.STRING
  }, {
    timestamps: false,
    freezeTableName: true,
    underscored: true
  });
  _class.associate = function (models) {
    _class.hasMany(models.student);
  };
  return _class;
};
複製代碼

1五、編輯server.js

...
const Class = require('./db/models')._class;

//獲取班級信息以及班級裏的全部學生
router.get('/classes', async ctx => {
    //獲取全部班級以及學生信息
     ctx.body = await Class.findAll({ include: [Student] });
});
...
複製代碼

belongsTo(一對一)

一個學生只能屬於一個班級,因此學生和班級的關係是一對一

一、修改./db/models/student.js文件

...
  student.associate = function(models) {
    student.belongsTo(models._class); //一對一
  };
 ...
複製代碼

二、修改server.js中獲取學生列表的接口

...
//獲取學生列表
router.get('/students', async ctx => {
    ctx.body = await Student.findAll({ include: [Class] });
});
...
複製代碼

belongsTo VS hasOne

student.belongsTo(models._class)這裏student叫作源模型,_class叫作目標模型

student表中包含了_class表的外鍵class_id,也就是說外鍵在源模型上面因此咱們使用belongsTo來建立關聯。

hasOnebelongsTo都是用來建立一對一關聯的,正確使用它們的方法就是看外鍵在哪一個模型中。

  • belongsTo關聯外鍵在源模型上
  • hasOne關聯外鍵在目標模型上

belongsToMany(多對多)

一個班級能夠有多名代課老師,一名代課老師能夠帶多個班級的課程。班級與老師的關係是多對多 爲了完成此功能的演示,咱們將作如下工做:

  1. 建立名稱

讓咱們開始吧!

一、生成teacher模型以及遷移文件

npx sequelize-cli model:generate --name teacher --attributes teacher_name:string
複製代碼

二、修改./db/migrations/xxxxx-teacher-class.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('teacher', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      teacher_name: {
        type: Sequelize.STRING(10),
        allowNull: false
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('teacher');
  }
};
複製代碼

三、生成teacher

npx sequelize-cli db:migrate
複製代碼

四、生成teacher表種子文件

npx sequelize-cli seed:generate --name init-teacher
複製代碼

五、編輯./db/seeders/xxxxx-init-teacher.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('teacher', [{
      teacher_name: '李老師'
    }, {
      teacher_name: '張老師'
    }]);
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('teacher', null, {});
  }
};
複製代碼

六、teacher表初始化數據

npx sequelize-cli db:seed  --seed  xxxxx-init-teacher.js
複製代碼

七、生成teacher_class模型以及遷移文件

npx sequelize-cli model:generate --name teacher_class --attributes teacher_id:integer,class_id:integer
複製代碼

八、編輯./db/migrations/xxxxx-create-teacher-class.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('teacher_class', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      teacher_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      class_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('teacher_class');
  }
};
複製代碼

九、生成teacher_class

npx sequelize-cli db:migrate
複製代碼

十、生成teacher_class表種子文件

npx sequelize-cli seed:generate --name init-teacher_class
複製代碼

十一、編輯./db/seeders/xxxxx-init-teacher_class.js

'use strict';

/* 李老師帶的班級爲一班和二班。張老師帶的班級爲三班 */
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('teacher_class', [{
      class_id: 1,
      teacher_id: 1
    }, {
      class_id: 2,
      teacher_id: 1
    }, {
      class_id: 3,
      teacher_id: 2
    }]);
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('teacher_class', null, {});
  }
};
複製代碼

十二、teacher_class表初始化數據

npx sequelize-cli db:seed  --seed  xxxxx-init-teacher_class.js
複製代碼

1三、編輯./db/models/teacher.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const teacher = sequelize.define('teacher', {
    teacher_name: DataTypes.STRING
  }, {
    timestamps: false,
    freezeTableName: true,
    underscored: true
  });
  teacher.associate = function (models) {
    teacher.belongsToMany(models._class, {
      through: models.teacher_class,
      foreignKey: 'teacher_id',
    });
  };
  return teacher;
};
複製代碼

1四、編輯./db/models/_class.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const _class = sequelize.define('_class', {
    class_name: DataTypes.STRING
  }, {
    timestamps: false,
    freezeTableName: true,
    underscored: true
  });
  _class.associate = function (models) {
    _class.hasMany(models.student);
    _class.belongsToMany(models.teacher, {
      through: models.teacher_class,
      foreignKey: 'class_id',
    });
  };
  return _class;
};
複製代碼

1五、編輯server.js

const Teacher = require('./db/models').teacher;

//獲取老師信息以及老師所帶的班級
router.get('/teachers', async ctx => {
    //獲取全部班級以及學生信息
     ctx.body = await Teacher.findAll({ include: [Class] });
})
複製代碼

查詢

基礎查詢

一、返回指定列

Student.findAll({
    attributes: ['id', 'student_name']
 });
 // select id,student_name from student
複製代碼

二、單條件查詢

Student.findAll({
    where: {
      id: 1
    }
 })
 // select * from student where id = 1
複製代碼

三、AND

//返回id爲1,姓名是`孫悟空`的學生信息
 Student.findAll({
        where: {
            id: 4,
            student_name:'孫悟空'
        }
    })
 // select * from student where id = 1 and student_name = '孫悟空'
複製代碼

四、OR

//返回年齡等於12或者22的學生信息
 Student.findAll({
     where: {
            student_age: {
                [Op.or]: [12, 22]
            }
        }
 })
 // select * from student where studnet_age = 12 or studnet_age = 22
複製代碼

五、條件查詢- >,>=,<,<=,=

// 返回年齡大於等於20的學生
 Student.findAll({
     where: {
            student_age: {
                [Op.gte]: 20
            }
        }
 })
 // select * from student where studnet_age >= 20
複製代碼
[Op.gt]: 6      //大於6
 [Op.gte]: 6     //大於等於6
 [Op.lt]: 10     //小於10
 [Op.lte]: 10    //小於等於10
 [Op.ne]: 20     //不等於20
 [Op.eq]: 3      //等於3
複製代碼

六、IN

// 返回年齡是16和18的學生信息
 Student.findAll({
     where: {
        student_age: {
            [Op.in]: [16,18]
        }
    }
 })
 // select * from student where studnet_age in (16,18)
複製代碼

七、LIKE

// 返回名稱包含'孫'的學生信息
 Student.findAll({
     where: {
        student_name: {
           [Op.like]: '%孫%',
        }
    }
 })
 // select * from student where studnet_name like '%孫%'
複製代碼

聚合函數

一、獲取學生的平均年齡

Student.findAll({
    attributes: [[sequelize.fn('AVG', sequelize.col('student_age')), 'avg']]
 })
複製代碼

二、獲取學生總數

Student.findAll({
     attributes: [[sequelize.fn('COUNT', sequelize.col('id')), 'count']]
 })
複製代碼

嵌套查詢

一、獲取一班全部的學生並根據年齡降序排列

Class.findAll({
    include: [{model: Student}],
    where:{id:1},
    order:[[Student,'student_age', 'DESC']]
    });
複製代碼

參考

sequelize中文文檔

相關文章
相關標籤/搜索