代码之家  ›  专栏  ›  技术社区  ›  jwkoo

排序模型、迁移文件和外键。哪一个是对的?

  •  4
  • jwkoo  · 技术社区  · 6 年前

    当我第一次开始学习Sequelize的时候,我只是不知道,只是在两个模型之间建立关系时复制和粘贴代码。

    我真的很困惑,是必须同时向模型文件和迁移文件插入外键,还是只为迁移文件插入外键。

    我知道迁移是具有更改数据库命令的文件。

    因此,我们必须手动将外键插入迁移文件,以便数据库可以创建它们。

    在Sequelize Doc中,如果我们添加像has many和own这样的关系,Sequelize将自动添加外键。

    所以我真的很困惑我是否需要添加它们。

    我在答案五五之前问了一些问题。

    有人说我们不必手动向模型添加外键,因为Sequelize会自动添加外键。

    但有些人说我们必须手动向模型添加外键,因为我们必须在模型和迁移文件之间匹配(同步)列。

    更糟糕的是,解释后继关系的文章是不同的。

    那么,哪一个是对的??

    我真的很想得到清楚的答案。

    如果有一些原因(如果我们必须向模型中添加外键),我们将非常感谢。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Akshay Gadhave    6 年前

    创建迁移时,还应该编写外键。也可以将它写在模型中,这样可以很容易地处理查询。 我们可以通过例子看到。考虑它们是两种表项和项类型

    1个项目类型有许多项目,因此,

    项目类型的迁移文件(migration创建项目类型.js)

    'use strict';
    module.exports = {
    up: function (queryInterface, Sequelize) {
        return queryInterface.createTable('item_types', {
            id: {
                allowNull: false,
                autoIncrement: true,
                primaryKey: true,
                type: Sequelize.INTEGER
            },
            item_type: {
                type: Sequelize.STRING
            },
            type_desc: {
                type: Sequelize.STRING
            },
            createdAt: {
                allowNull: true,
                type: Sequelize.DATE,
                defaultValue: Sequelize.NOW
            },
            updatedAt: {
                allowNull: true,
                type: Sequelize.DATE,
                defaultValue: Sequelize.NOW
            }
        });
    },
    down: function (queryInterface, Sequelize) {
        return queryInterface.dropTable('item_types');
    }
    };
    

    项目的迁移文件(migration_create_item.js)

    'use strict';
    module.exports = {
    up: function (queryInterface, Sequelize) {
        return queryInterface.createTable('items', {
            id: {
                allowNull: false,
                autoIncrement: true,
                primaryKey: true,
                type: Sequelize.INTEGER
            },
            item_name: {
                type: Sequelize.STRING
            },
            item_desc: {
                type: Sequelize.STRING
            },
            item_type_id: {
                type: Sequelize.INTEGER,
                references: {
                    model: 'item_types',
                    key: 'id'
                }
            },
            createdAt: {
                allowNull: false,
                type: Sequelize.DATE
            },
            updatedAt: {
                allowNull: false,
                type: Sequelize.DATE
            }
        });
    },
    down: function (queryInterface, Sequelize) {
        return queryInterface.dropTable('items');
    }
    };
    

    请注意,总是先创建父表,然后创建其他表,即创建所有没有外键的表,然后创建其他表。

    模型文件项类型(项类型.js)

    'use strict';
    module.exports = function (sequelize, DataTypes) {
    var item_type = sequelize.define('item_type', {
        item_type: DataTypes.STRING,
        type_desc: DataTypes.STRING
    });
    item_type.associate = function (models) {
        item_type.hasMany(models.item, {foreignKey: 'item_type_id'});
    };
    return item_type;
    };
    

    项目的模型文件(item.js)

    'use strict';
     var Logger = require('./../utils/logger');
    
     var log = new Logger('item_type_factory');
     module.exports = function (sequelize, DataTypes) {
     var item = sequelize.define('item', {
        item_name: DataTypes.STRING,
        item_desc: DataTypes.STRING
     });
     item.associate = function (models) {
        item.item_type = item.belongsTo(models.item_type, {foreignKey: 'id', target_key: 'item_type_id'});
        item.order_details = item.hasMany(models.order_details);
        item.user = item.belongsToMany(models.user, {through: 'supplier_items'})
    };
    
    item.addNewItem = function (data) {
        return item.create(data, {include: [{association: item.item_type}]});
    };
    
    item.findAndCreate = function (data, item_name) {
        return new Promise(function (resolve, reject) {
            item.findOrCreate({
                where: {'item_name': item_name}, defaults: data
            }).spread(function (record_data, created) {
                resolve(record_data);
            }).catch(function (insert_error) {
                reject(insert_error);
            });
        });
    };
    
    item.findAllItems = function () {
        return item.findAll({
            include: [{association: item.item_type}]
        });
    };
    return item;
    };
    

    有关亮片的基础知识,您可以参考以下文章, Getting started with Sequelize 仅用于基础。

        2
  •  2
  •   AbhinavD    6 年前

    我们应该如何创建数据库模式

    我们有两种选择。迁移或使用 sync . 总是喜欢迁移而不是 同步 . 迁移功能更强大,您可以使用它撤消、重做和执行更多操作。 同步 不反映表格更改。例如,您定义了一个特定的模型 User 忘了补充 gender . 现在,如果您想用sequelize添加此列,则必须使用 force:true 这会让你 用户 生产中不需要的数据。

    谁应该定义外键约束

    从软件设计原则来看,无论应用程序逻辑(sequelize)是否实现相同的逻辑,您的数据库约束和验证都应该始终到位。例如,一个新的开发人员可以编写一个原始查询,如果没有正确的约束,则可能会破坏整个数据库。

    但是,我们还希望使用Sequelize对所有关联进行正确的查询。如果Sequelize知道数据库中存在哪些关联以及什么应该是外键,那么它就可以这样做。

    因此,在迁移和顺序级别都应该定义外键约束。

    数据库约束示例

    enter image description here

    如上图所示,约束是在我的数据库模式上定义的。

    连续约束示例

    module.exports = (sequelize, DataTypes) => {
      const Designation = sequelize.define('designation', {
        doctorId: {
          type: DataTypes.STRING,
          allowNull: false,
          field: 'doctor_id',
        },
        name: {
          type: DataTypes.STRING,
          allowNull: false,
        },
      }, {});
      Designation.associate = (models) => {
        models.designation.belongsTo(models.doctor, {
          onDelete: 'cascade',
        });
      };