在EggJS中使用Sequelize作聯表查詢

【轉發請註明出處】 我的博客地址:小猴的代碼筆記html

1.EggJS引用Sequelize

  1. 安裝sequelize依賴和mysql驅動mysql

    cnpm i egg-sequelize mysql2 -S
    複製代碼
  2. 啓用sequelize插件git

    在config/plugin.js裏面添加github

    sequelize: {
        enable: true,
        package: 'egg-sequelize',
    },
    複製代碼
  3. 配置數據庫sql

    在config/config.default.js裏面添加數據庫

    config.sequelize = {
        dialect: 'mysql',  // 表示使用mysql
        host: '127.0.0.1', // 鏈接的數據庫主機地址
        port: 3306, // mysql服務端口
        database: 'demo', // 數據庫名
        username: 'root',  // 數據庫用戶名
        password: 'root', // 數據庫密碼
        define: {  // model的全局配置
          	timestamps: true,   // 添加create,update,delete時間戳
          	paranoid: true,   // 添加軟刪除
          	freezeTableName: true,  // 防止修改表名爲複數
          	underscored: false  // 防止駝峯式字段被默認轉爲下劃線
        },
        timezone: '+8:00',  // 因爲orm用的UTC時間,這裏必須加上東八區,不然取出來的時間相差8小時
        dialectOptions: {  // 讓讀取date類型數據時返回字符串而不是UTC時間
            dateStrings: true,
            typeCast(field, next) {
                if (field.type === "DATETIME") {
                    return field.string();
                }
                return next();
            }
        }
    };
    複製代碼

2.定義Model

  1. 剛開始使用egg-init構建的Egg項目是沒有app/model目錄的,初始的項目結構以下:npm

    itzishu
    ├── README.md
    ├── app
    │   ├── controller
    │   │   └── home.js
    │   └── router.js
    ├── appveyor.yml
    ├── config
    │   ├── config.default.js
    │   └── plugin.js
    ├── package.json
    └── test
        └── app
            └── controller
                └── home.test.js
    複製代碼

    先在app目錄下新建一個目錄爲model,裏面用來存放全部的數據庫裏面定義的表的實例對象內容。json

  2. 數據庫表的內容以下:數組

    /*
     Navicat Premium Data Transfer
    
     Source Server         : 系統數據庫3306
     Source Server Type    : MySQL
     Source Server Version : 50725
     Source Host           : localhost:3306
     Source Schema         : demo
    
     Target Server Type    : MySQL
     Target Server Version : 50725
     File Encoding         : 65001
    
     Date: 12/05/2019 15:11:37
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for classes
    -- ----------------------------
    DROP TABLE IF EXISTS `classes`;
    CREATE TABLE `classes` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(50) NOT NULL,
      `createdAt` datetime DEFAULT NULL,
      `updatedAt` datetime DEFAULT NULL,
      `deletedAt` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of classes
    -- ----------------------------
    BEGIN;
    INSERT INTO `classes` VALUES (1, '軟件工程1601', '2019-05-12 13:11:43', '2019-05-12 13:11:47', NULL);
    INSERT INTO `classes` VALUES (2, '網絡工程1601', '2019-05-12 13:12:10', '2019-05-12 13:12:13', NULL);
    COMMIT;
    
    -- ----------------------------
    -- Table structure for info
    -- ----------------------------
    DROP TABLE IF EXISTS `info`;
    CREATE TABLE `info` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(50) NOT NULL,
      `age` int(11) NOT NULL,
      `sex` tinyint(255) NOT NULL DEFAULT '1' COMMENT '1爲男,0爲女',
      `studentId` int(11) NOT NULL,
      `createdAt` datetime DEFAULT NULL,
      `updatedAt` datetime DEFAULT NULL,
      `deletedAt` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of info
    -- ----------------------------
    BEGIN;
    INSERT INTO `info` VALUES (1, '許仙', 23, 1, 1, '2019-05-12 13:25:58', '2019-05-12 13:26:01', NULL);
    INSERT INTO `info` VALUES (2, '白素貞', 20, 0, 2, '2019-05-12 13:26:41', '2019-05-12 13:26:46', NULL);
    INSERT INTO `info` VALUES (3, '法海', 22, 1, 3, '2019-05-12 13:27:20', '2019-05-12 13:27:22', NULL);
    INSERT INTO `info` VALUES (4, '小青', 18, 0, 4, '2019-05-12 13:27:48', '2019-05-12 13:27:51', NULL);
    INSERT INTO `info` VALUES (5, '金如意', 20, 0, 5, '2019-05-12 13:28:34', '2019-05-12 13:28:37', NULL);
    INSERT INTO `info` VALUES (6, '景鬆', 23, 1, 6, '2019-05-12 13:30:07', '2019-05-12 13:30:10', NULL);
    COMMIT;
    
    -- ----------------------------
    -- Table structure for lession
    -- ----------------------------
    DROP TABLE IF EXISTS `lession`;
    CREATE TABLE `lession` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(50) NOT NULL,
      `createdAt` datetime DEFAULT NULL,
      `updatedAt` datetime DEFAULT NULL,
      `deletedAt` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of lession
    -- ----------------------------
    BEGIN;
    INSERT INTO `lession` VALUES (1, '計算機網絡', '2019-05-12 13:12:32', '2019-05-12 13:12:35', NULL);
    INSERT INTO `lession` VALUES (2, 'Java程序設計', '2019-05-12 13:12:50', '2019-05-12 13:12:52', NULL);
    INSERT INTO `lession` VALUES (3, '軟件項目管理', '2019-05-12 13:13:07', '2019-05-12 13:13:10', NULL);
    INSERT INTO `lession` VALUES (4, '網絡安全', '2019-05-12 13:13:22', '2019-05-12 13:13:25', NULL);
    COMMIT;
    
    -- ----------------------------
    -- Table structure for lession_student
    -- ----------------------------
    DROP TABLE IF EXISTS `lession_student`;
    CREATE TABLE `lession_student` (
      `lessionId` int(11) NOT NULL,
      `studentId` int(11) NOT NULL,
      `createdAt` datetime DEFAULT NULL,
      `updatedAt` datetime DEFAULT NULL,
      `deletedAt` datetime DEFAULT NULL,
      PRIMARY KEY (`lessionId`,`studentId`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of lession_student
    -- ----------------------------
    BEGIN;
    INSERT INTO `lession_student` VALUES (1, 1, '2019-05-12 13:20:35', '2019-05-12 13:20:40', NULL);
    INSERT INTO `lession_student` VALUES (1, 2, '2019-05-12 13:20:51', '2019-05-12 13:20:53', NULL);
    INSERT INTO `lession_student` VALUES (1, 3, '2019-05-12 13:21:02', '2019-05-12 13:21:05', NULL);
    INSERT INTO `lession_student` VALUES (1, 4, '2019-05-12 13:21:15', '2019-05-12 13:21:19', NULL);
    INSERT INTO `lession_student` VALUES (1, 5, '2019-05-12 13:21:29', '2019-05-12 13:21:32', NULL);
    INSERT INTO `lession_student` VALUES (1, 6, '2019-05-12 13:21:43', '2019-05-12 13:21:45', NULL);
    INSERT INTO `lession_student` VALUES (2, 1, '2019-05-12 13:23:10', '2019-05-12 13:23:13', NULL);
    INSERT INTO `lession_student` VALUES (2, 3, '2019-05-12 13:23:28', '2019-05-12 13:23:31', NULL);
    INSERT INTO `lession_student` VALUES (2, 4, '2019-05-12 13:23:40', '2019-05-12 13:23:43', NULL);
    INSERT INTO `lession_student` VALUES (2, 5, '2019-05-12 13:23:54', '2019-05-12 13:23:57', NULL);
    INSERT INTO `lession_student` VALUES (3, 1, '2019-05-12 13:24:21', '2019-05-12 13:24:24', NULL);
    INSERT INTO `lession_student` VALUES (3, 4, '2019-05-12 13:24:39', '2019-05-12 13:24:42', NULL);
    INSERT INTO `lession_student` VALUES (4, 2, '2019-05-12 13:24:59', '2019-05-12 13:25:03', NULL);
    INSERT INTO `lession_student` VALUES (4, 6, '2019-05-12 13:25:12', '2019-05-12 13:25:15', NULL);
    COMMIT;
    
    -- ----------------------------
    -- Table structure for student
    -- ----------------------------
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `number` varchar(12) NOT NULL COMMENT '學號',
      `password` varchar(32) NOT NULL,
      `classId` int(11) NOT NULL,
      `createdAt` datetime DEFAULT NULL,
      `updatedAt` datetime DEFAULT NULL,
      `deletedAt` datetime DEFAULT NULL,
      PRIMARY KEY (`id`,`number`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of student
    -- ----------------------------
    BEGIN;
    INSERT INTO `student` VALUES (1, '160101', '202cb962ac59075b964b07152d234b70', 1, '2019-05-12 13:16:09', '2019-05-12 13:16:12', NULL);
    INSERT INTO `student` VALUES (2, '160201', '202cb962ac59075b964b07152d234b70', 2, '2019-05-12 13:16:32', '2019-05-12 13:16:35', NULL);
    INSERT INTO `student` VALUES (3, '160102', '202cb962ac59075b964b07152d234b70', 1, '2019-05-12 13:17:17', '2019-05-12 13:17:21', NULL);
    INSERT INTO `student` VALUES (4, '160103', '202cb962ac59075b964b07152d234b70', 1, '2019-05-12 13:17:51', '2019-05-12 13:17:54', NULL);
    INSERT INTO `student` VALUES (5, '160104', '202cb962ac59075b964b07152d234b70', 1, '2019-05-12 13:18:13', '2019-05-12 13:18:16', NULL);
    INSERT INTO `student` VALUES (6, '160202', '202cb962ac59075b964b07152d234b70', 2, '2019-05-12 13:18:36', '2019-05-12 13:18:39', NULL);
    COMMIT;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    複製代碼

    其中,各個表之間存在聯繫爲:安全

    • student與info存在一對一關係
    • classes與student存在一對多關係
    • student與lession存在多對多關係,中間表爲lession_student
  3. 根據數據表的結構,咱們肯定關係並寫好model目錄下相關文件

    • student.js
    module.exports = app => {
        const { STRING, INTEGER } = app.Sequelize;
    
        const Student = app.model.define('student', {
            id: {
                type: INTEGER,
                autoIncrement: true,
                primaryKey: true
            },
            number: {
                type: STRING,
                allowNull: false,
            },
            password: {
                type: STRING(32),
                allowNull: false
            },
            classId: {
                type: INTEGER,
                allowNull: false
            }
        });
    
        Student.associate = function (){
            // 與Info存在一對多關係,因此是hasOne()
            app.model.Student.hasOne(app.model.Info, {foreignKey: 'studentId'});
            // 與Classes存在多對一關係,因此使用belongsTo()
            app.model.Student.belongsTo(app.model.Classes, {foreignKey: 'classId', targetKey: 'id'});
            // 與Lessison存在多對多關係,使用belongsToMany()
            app.model.Student.belongsToMany(app.model.Lession, {
                through: app.model.LessionStudent,
                foreignKey: 'studentId',
                otherKey: 'lessionId'
            });
        }
    
        return Student;
    }
    複製代碼
    • info.js
    module.exports = app => {
        const { STRING, INTEGER, BOOLEAN } = app.Sequelize;
    
        const Info = app.model.define('info', {
            id: {
                type: INTEGER,
                autoIncrement: true,
                primaryKey: true
            },
            name: {
                type: STRING(50),
                allowNull: false,
            },
            age: {
                type: INTEGER,
                allowNull: false
            },
            sex: {
                type: BOOLEAN,
                allowNull: false,
                get() {
                    if ( this.getDataValue('sex') ){
                        return '男';
                    }else {
                        return '女';
                    }
                }
            },
            studentId: {
                type: INTEGER,
                allowNull: false
            }
        });
    
        Info.associate = function (){
            app.model.Info.belongsTo(app.model.Student, {foreignKey: 'studentId', targetKey: 'id'});
        }
    
        return Info;
    }
    複製代碼

    這裏注意下,在sex字段中,有一個get(){}方法,由於在數據表裏面,sex字段存了1或0 ,1爲男0爲女,爲了直接返回"男"或"女",這裏使用get方法在找到數據後先作了處理,那返回給調用的函數的數據就是咱們設置的值

    • classes.js
    module.exports = app => {
        const { STRING, INTEGER, BOOLEAN } = app.Sequelize;
    
        const Classes = app.model.define('classes', {
            id: {
                type: INTEGER,
                autoIncrement: true,
                primaryKey: true
            },
            name: {
                type: STRING(50),
                allowNull: false,
            },
            age: {
                type: INTEGER,
                allowNull: false
            },
            sex: {
                type: BOOLEAN,
                allowNull: false,
                get() {
                    if ( this.getDataValue('sex') ){
                        return '男';
                    }else {
                        return '女';
                    }
                }
            },
            studentId: {
                type: INTEGER,
                allowNull: false
            }
        });
    
        Classes.associate = function (){
            // classes與student是一對多關係,因此這裏使用hasMany()
            app.model.Classes.hasMany(app.model.Student, {foreignKey: 'classId', targetKey: 'id'});
        }
    
        return Classes;
    }
    複製代碼
    • lession.js
    module.exports = app => {
        const { INTEGER, STRING } = app.Sequelize;
    
        const Lession = app.model.define('lession', {
            id: {
                type: INTEGER,
                primaryKey: true,
                autoIncrement: true
            },
            name: {
                type: STRING,
                allowNull: false
            }
        });
    
        Lession.associate = function(){
            // 與student表是多對多關係
            app.model.Lession.belongsToMany(app.model.Student, {
                through: app.model.LessionStudent,
                foreignKey: 'lessionId',
                otherKey: 'studentId'
            });
        }
    
        return Lession;
    }
    複製代碼
    • lession-student.js
    module.exports = app => {
        const { INTEGER } = app.Sequelize;
    
        const LessionStudent = app.model.define('lession_student', {
            lessionId: {
                type: INTEGER,
                primaryKey: true
            },
            studentId: {
                type: INTEGER,
                primaryKey: true
            }
        });
    
        LessionStudent.associate = function(){
    
        }
    
        return LessionStudent;
    }
    複製代碼
  4. 總結一下Model定義的內容

    • 針對MYSQL經常使用的字段類型

    字段類型從 app.Sequelize 獲取,對應名字以下

    Sequelize.STRING                      // VARCHAR(255)
    Sequelize.STRING(1234)                // VARCHAR(1234)
    Sequelize.STRING.BINARY               // VARCHAR BINARY
    Sequelize.TEXT                        // TEXT
    Sequelize.TEXT('tiny')                // TINYTEXT
    
    Sequelize.INTEGER                     // INTEGER
    Sequelize.BIGINT                      // BIGINT
    Sequelize.BIGINT(11)                  // BIGINT(11)
    
    Sequelize.FLOAT                       // FLOAT
    Sequelize.FLOAT(11)                   // FLOAT(11)
    Sequelize.FLOAT(11, 12)               // FLOAT(11,12)
    
    Sequelize.DOUBLE                      // DOUBLE
    Sequelize.DOUBLE(11)                  // DOUBLE(11)
    Sequelize.DOUBLE(11, 12)              // DOUBLE(11,12)
    
    Sequelize.DECIMAL                     // DECIMAL
    Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)
    
    Sequelize.DATE                        // DATETIME 針對 mysql / sqlite, TIMESTAMP WITH TIME ZONE 針對 postgres
    Sequelize.DATE(6)                     // DATETIME(6) 針對 mysql 5.6.4+. 小數秒支持多達6位精度
    Sequelize.DATEONLY                    // DATE 不帶時間.
    Sequelize.BOOLEAN                     // TINYINT(1)
    複製代碼

    其餘的數據庫所容許的類型參考:數據類型

    • 字段屬性值
    屬性名 類型 默認值 說明 說明
    type Any 數據類型
    primaryKey Boolean false 主鍵
    autoIncrement Boolean false 自增
    allowNull Boolean false 是否容許爲空
    defaultValue Any 默認值
    field String 字段名 自定義字段名
    unique Any 約束
    • 表與表的關聯性

    在sequelize中,表與表之間用代碼來講存在三種關聯關係:一對一,一對多,多對多

    1. 一對一

      在該項目中,student表和info表是存在一對一關係的,一個學生有一條專屬信息。

      在student.js中,使用了hasOne()方法,第一個參數爲關聯的模型對象Info,第二個參數爲一個對象,其包含一個屬性爲foreginKey爲對應的信息表中studentId字段

      在info.js中,使用了belongsTo()方法,第一個參數爲關聯的模型對象Student, 第二個參數也是一個對象,其有兩個屬性,foreginKey爲info表中的"studentId"字段,第二個參數targetKey爲student表中的"id"字段

      總結: hasOne()和belongsTo()第一個參數爲本表關聯的另一個表的Model實例,第二個參數中,都有foreginKey屬性,對hasOne來講,這個屬性值是對方表與本身Id對應的字段,對belongsTo來講,這個屬性值是本表上的與對方表id對應的字段名。belongsTo比hasOne多了個targetKey屬性,其爲對方表的對應主鍵名

    2. 一對多

      classes與student是一對多的關係,一個班級有多個學生,多個學生組成一個班級。

      在student.js中,使用了belongsTo(),在classes.js中,使用了hasMany(),發現hasMany()與belongsTo()所須要的參數是相似的,可是這裏注意,hasMany()裏面的foreginKey值是對方表的classesId。結合第上面"一對一"的分析,咱們能夠總結出:

      has開頭的方法中,foreginKey屬性值從對方的表上找,若是有targetKey的值則是本身的主鍵;

      belongs開頭的方法中,foreginKey屬性值在自身表上找,targetKey屬性值則是對方表上

    3. 多對多

      分析多對多關係,一個學生有多門課,一個課有多個學生,那咱們能夠用一箇中間表lession-student.js作這個聯繫。

      在student.js中,咱們使用了belongsToMany()方法,lession.js文件中也是如此,經過該方法的參數內容,能夠發現其多了一個through屬性,其值是中間表的Model實例。根據上面的規律,belongs開頭的方法裏面foreginKey找本身,otherKey找其餘,因此很容易理解。

    總結: 在Model的實例裏面,重寫Model的associate方法,將關聯的關係放到裏面。

    一對一的方法有:hasOne(Model, {foreignKey:對方,})belongsTo(Model,{foreignKey:本身,targetKey:對方})

    一對多的方法有: hasMany(Model,{foreignKey:對方, targetKey:本身})belongsTo(Model,{foreignKey:本身,targetKey:對方})

    多對多的方法有: belongsToMany(Model,{through:Model, targetKey:本身, otherKey:對方})

3.聯表查詢

  • 一對一

    在controller裏面以下寫

    // 獲取學生信息 經過一對多的聯繫
        async info(){
            const { ctx, app } = this;
            let result = await app.model.Student.findAll({
              include: {
                model: app.model.Info
              }
            });
            ctx.body = result;
        }
    複製代碼

    獲取到的值以下:

    [
    		// 第一個學生
        {
            "id": 1,
            "number": "160101",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 1,
            "createdAt": "2019-05-12 13:16:09",
            "updatedAt": "2019-05-12 13:16:12",
            "deletedAt": null,
            "info": {  // 聯表查到的信息
                "sex": "男",
                "id": 1,
                "name": "許仙",
                "age": 23,
                "studentId": 1,
                "createdAt": "2019-05-12 13:25:58",
                "updatedAt": "2019-05-12 13:26:01",
                "deletedAt": null
            }
        },
      	// 第二個學生
        {
            "id": 2,
            "number": "160201",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 2,
            "createdAt": "2019-05-12 13:16:32",
            "updatedAt": "2019-05-12 13:16:35",
            "deletedAt": null,
            "info": {
                "sex": "女",
                "id": 2,
                "name": "白素貞",
                "age": 20,
                "studentId": 2,
                "createdAt": "2019-05-12 13:26:41",
                "updatedAt": "2019-05-12 13:26:46",
                "deletedAt": null
            }
        },
        {
            "id": 3,
            "number": "160102",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 1,
            "createdAt": "2019-05-12 13:17:17",
            "updatedAt": "2019-05-12 13:17:21",
            "deletedAt": null,
            "info": {
                "sex": "男",
                "id": 3,
                "name": "法海",
                "age": 22,
                "studentId": 3,
                "createdAt": "2019-05-12 13:27:20",
                "updatedAt": "2019-05-12 13:27:22",
                "deletedAt": null
            }
        },
        {
            "id": 4,
            "number": "160103",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 1,
            "createdAt": "2019-05-12 13:17:51",
            "updatedAt": "2019-05-12 13:17:54",
            "deletedAt": null,
            "info": {
                "sex": "女",
                "id": 4,
                "name": "小青",
                "age": 18,
                "studentId": 4,
                "createdAt": "2019-05-12 13:27:48",
                "updatedAt": "2019-05-12 13:27:51",
                "deletedAt": null
            }
        },
        {
            "id": 5,
            "number": "160104",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 1,
            "createdAt": "2019-05-12 13:18:13",
            "updatedAt": "2019-05-12 13:18:16",
            "deletedAt": null,
            "info": {
                "sex": "女",
                "id": 5,
                "name": "金如意",
                "age": 20,
                "studentId": 5,
                "createdAt": "2019-05-12 13:28:34",
                "updatedAt": "2019-05-12 13:28:37",
                "deletedAt": null
            }
        },
        {
            "id": 6,
            "number": "160202",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 2,
            "createdAt": "2019-05-12 13:18:36",
            "updatedAt": "2019-05-12 13:18:39",
            "deletedAt": null,
            "info": {
                "sex": "男",
                "id": 6,
                "name": "景鬆",
                "age": 23,
                "studentId": 6,
                "createdAt": "2019-05-12 13:30:07",
                "updatedAt": "2019-05-12 13:30:10",
                "deletedAt": null
            }
        }
    ]
    複製代碼
  • 一對多

    // 獲取班級名爲 軟件工程1601 的班級學生
        async student(){
          const { ctx, app } = this;
          let result = await app.model.Classes.findAll({
            where: {
              name: '軟件工程1601'
            },
            include: {
              model: app.model.Student
            }
          })
          ctx.body = result;
        }
    複製代碼

    獲取數據以下:

    [
        {
            "id": 1,
            "name": "軟件工程1601",
            "createdAt": "2019-05-12 13:11:43",
            "updatedAt": "2019-05-12 13:11:47",
            "deletedAt": null,
            "students": [
                {
                    "id": 1,
                    "number": "160101",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 1,
                    "createdAt": "2019-05-12 13:16:09",
                    "updatedAt": "2019-05-12 13:16:12",
                    "deletedAt": null
                },
                {
                    "id": 3,
                    "number": "160102",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 1,
                    "createdAt": "2019-05-12 13:17:17",
                    "updatedAt": "2019-05-12 13:17:21",
                    "deletedAt": null
                },
                {
                    "id": 4,
                    "number": "160103",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 1,
                    "createdAt": "2019-05-12 13:17:51",
                    "updatedAt": "2019-05-12 13:17:54",
                    "deletedAt": null
                },
                {
                    "id": 5,
                    "number": "160104",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 1,
                    "createdAt": "2019-05-12 13:18:13",
                    "updatedAt": "2019-05-12 13:18:16",
                    "deletedAt": null
                }
            ]
        }
    ]
    複製代碼
  • 多對多

    從學生獲取課程信息

    // 獲取學生的選課內容
        async lession(){
          const { ctx, app } = this;
          let result = await app.model.Student.findAll({
            where:{
              id: 1,
            },
            include: [
              {model: app.model.Info},
              {model: app.model.Lession}
            ]
          });
          ctx.body = result;
        }
    複製代碼

    這裏的話,注意include的值爲一個數組了,這樣能夠多個聯表獲取數據

    數據以下:

    [
        {
            "id": 1,
            "number": "160101",
            "password": "202cb962ac59075b964b07152d234b70",
            "classId": 1,
            "createdAt": "2019-05-12 13:16:09",
            "updatedAt": "2019-05-12 13:16:12",
            "deletedAt": null,
            "info": {
                "sex": "男",
                "id": 1,
                "name": "許仙",
                "age": 23,
                "studentId": 1,
                "createdAt": "2019-05-12 13:25:58",
                "updatedAt": "2019-05-12 13:26:01",
                "deletedAt": null
            },
            "lessions": [
                {
                    "id": 1,
                    "name": "計算機網絡",
                    "createdAt": "2019-05-12 13:12:32",
                    "updatedAt": "2019-05-12 13:12:35",
                    "deletedAt": null,
                    "lession_student": {
                        "lessionId": 1,
                        "studentId": 1,
                        "createdAt": "2019-05-12 13:20:35",
                        "updatedAt": "2019-05-12 13:20:40",
                        "deletedAt": null
                    }
                },
                {
                    "id": 2,
                    "name": "Java程序設計",
                    "createdAt": "2019-05-12 13:12:50",
                    "updatedAt": "2019-05-12 13:12:52",
                    "deletedAt": null,
                    "lession_student": {
                        "lessionId": 2,
                        "studentId": 1,
                        "createdAt": "2019-05-12 13:23:10",
                        "updatedAt": "2019-05-12 13:23:13",
                        "deletedAt": null
                    }
                },
                {
                    "id": 3,
                    "name": "軟件項目管理",
                    "createdAt": "2019-05-12 13:13:07",
                    "updatedAt": "2019-05-12 13:13:10",
                    "deletedAt": null,
                    "lession_student": {
                        "lessionId": 3,
                        "studentId": 1,
                        "createdAt": "2019-05-12 13:24:21",
                        "updatedAt": "2019-05-12 13:24:24",
                        "deletedAt": null
                    }
                }
            ]
        }
    ]
    複製代碼

    從課程獲取選課學生:

    // 獲取某個課的參課學生
        async lessionStudent(){
          const { ctx, app } = this;
          let result = await app.model.Lession.findAll({
            where:{
              name: '網絡安全'
            },
            include: {
              model: app.model.Student,
              include: {
                model: app.model.Info
              }
            }
          });
          ctx.body = result;
        }
    複製代碼

    這裏注意,在include的下面又有一個include,第二個include是相對Student表的

    數據以下:

    [
        {
            "id": 4,
            "name": "網絡安全",
            "createdAt": "2019-05-12 13:13:22",
            "updatedAt": "2019-05-12 13:13:25",
            "deletedAt": null,
            "students": [
                {
                    "id": 2,
                    "number": "160201",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 2,
                    "createdAt": "2019-05-12 13:16:32",
                    "updatedAt": "2019-05-12 13:16:35",
                    "deletedAt": null,
                    "lession_student": {
                        "lessionId": 4,
                        "studentId": 2,
                        "createdAt": "2019-05-12 13:24:59",
                        "updatedAt": "2019-05-12 13:25:03",
                        "deletedAt": null
                    },
                    "info": {
                        "sex": "女",
                        "id": 2,
                        "name": "白素貞",
                        "age": 20,
                        "studentId": 2,
                        "createdAt": "2019-05-12 13:26:41",
                        "updatedAt": "2019-05-12 13:26:46",
                        "deletedAt": null
                    }
                },
                {
                    "id": 6,
                    "number": "160202",
                    "password": "202cb962ac59075b964b07152d234b70",
                    "classId": 2,
                    "createdAt": "2019-05-12 13:18:36",
                    "updatedAt": "2019-05-12 13:18:39",
                    "deletedAt": null,
                    "lession_student": {
                        "lessionId": 4,
                        "studentId": 6,
                        "createdAt": "2019-05-12 13:25:12",
                        "updatedAt": "2019-05-12 13:25:15",
                        "deletedAt": null
                    },
                    "info": {
                        "sex": "男",
                        "id": 6,
                        "name": "景鬆",
                        "age": 23,
                        "studentId": 6,
                        "createdAt": "2019-05-12 13:30:07",
                        "updatedAt": "2019-05-12 13:30:10",
                        "deletedAt": null
                    }
                }
            ]
        }
    ]
    複製代碼

4. 總結

用時4小時,調試加數據庫設置,代碼編寫,查文檔。容許我偷個懶,不想總結了,仔細閱讀內容,基本上能夠了解Sequelize在聯表查詢上的基本用法了

相關文章
相關標籤/搜索