【问题标题】:How can I make a composite unique constraint with foreign keys and regular keys in Sequelize?如何在 Sequelize 中使用外键和常规键创建复合唯一约束?
【发布时间】:2017-12-18 20:04:53
【问题描述】:

我们有两个模型,用户和项目。在 User.js 下

User = Model.define('User', {
    id: {
        type: DataType.UUID,
        defaultValue: DataType.UUIDV1,
        primaryKey: true,
    },
});

在 Item.js 下

Item = Model.define('Item', {
    id: {
        type: DataType.UUID,
        defaultValue: DataType.UUIDV1,
        primaryKey: true,
    },
});

这是他们的关联,一个用户可以有很多项。

User.hasMany(Items, {
    foreignKey: {
        allowNull: false,
        name: 'itemId',
    },
    onUpdate: 'cascade',
    onDelete: 'cascade',
});

假设每个用户可能只有每种类型的项目之一。 如何为此添加唯一约束?以下代码不起作用。

User.hasMany(Items, {
    foreignKey: {
        allowNull: false,
        name: 'itemId',
        unique: 'userItemUnique',
    },
    onUpdate: 'cascade',
    onDelete: 'cascade',
});

Item = Model.define('Item', {
    id: {
        type: DataType.UUID,
        defaultValue: DataType.UUIDV1,
        primaryKey: true,
        unique: 'userItemUnique',
    },
});

【问题讨论】:

    标签: node.js sqlite foreign-keys sequelize.js unique-constraint


    【解决方案1】:

    您可以为此使用迁移。

    Sequelize-cli 提供了 addConstraint 和 andIndex 方法,可以用来实现

    来自docs

    queryInterface.addConstraint('Users', ['email'],
     { type: 'unique', name: 'custom_unique_constraint_name'
     }); 
    

    【讨论】:

    • 为什么一定要通过Sequelize-cli添加约束?有没有办法通过 Sequelize 本身来做到这一点?
    • 你可以使用索引来做到这一点 [This](github.com/sequelize/sequelize/issues/3468) 问题的详细信息虽然这样做 imo 感觉不是很干净
    【解决方案2】:

    如果有人仍在关注此问题,我通过在需要唯一约束的模型中手动定义外键来解决此问题(您仍然可以使用 sequelize 关联,例如.hasMany)。

    关于您自己的代码,我认为当您请求 Assume that each user may only have one of each type of item 时可能会产生混淆,因为您没有定义什么是项目类型。

    我根据自己的理解起草了一些内容,并考虑了我之前的评论。

    User = Model.define('User', {
        id: {
            type: DataType.UUID,
            defaultValue: DataType.UUIDV1,
            primaryKey: true,
            allowNull: false,
            validate: {
              isUUID: 1,
            },
        },
    });
    
    Item = Model.define('Item', {
        id: {
            type: DataType.UUID,
            defaultValue: DataType.UUIDV1,
            primaryKey: true,
            allowNull: false,
            validate: {
              isUUID: 1,
            },
        },
        type: {
            type: DataType.STRING,
            unique: 'uniqueUserItemType' // see note 1
        }
        userId: { 
            type: DataType.UUID,
            references: { // see note 2
              model: User,
              key: 'id',
            },
            unique: 'uniqueUserItemType',
        }
    });
    
    User.hasMany(Item, {
        foreignKey: {
            allowNull: false,
            name: 'itemId',
        },
        onUpdate: 'cascade',
        onDelete: 'cascade',
    });
    
    Item.belongsTo(User);
    
    

    我还按照 Sequelize 的建议添加了 belongsTo 关联。

    [1] 关于复合唯一约束here的更多信息。

    [2] 更多关于模型here 内部外键定义的信息。

    【讨论】:

    • 我唯一要补充的是,在定义中手动创建外键后,您可以像这样使用索引命令........索引:[{唯一:真, fields: ['name','user_id'] }] 来创建复合键,这可以从我所看到的正确创建它。我将很快添加一个答案以更详细地展示这一点
    【解决方案3】:

    就我而言,我根据 Joel Barenco 的回答做了类似的事情。

    const { Model, DataTypes } = require('sequelize');
    const User = require('../models/user');
    
    module.exports = function(sequelize){
        class Algorithm extends Model {}
        UserModel = User(sequelize);//@JA - Gets a defined version of user class
    
        var AlgorithmFrame = Algorithm.init({
            id: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                autoIncrement: true
            },
            name: {
                type: DataTypes.STRING,
                allowNull: false,
            },
            user_Id: {
                type: DataTypes.INTEGER,
                references: { 
                    model: UserModel,
                    key: 'id',
                },
            }
        }, {
          sequelize,
          modelName: 'Algorithm',
          indexes: [{ unique: true, fields: ['name','user_id'] }]
        });
    
        return AlgorithmFrame
    };
    

    这里的想法是手动创建外键,但你可以用indexes: [{ unique: true, fields: ['name','user_id'] }]定义唯一索引

    我的策略还展示了如何在类中定义模型。要调用它,您只需像这样将 sequelize 传递给它,其中 sequelize 是保存所有连接信息等的变量...

    const Algorithm = require('../models/algorithm');
    const AlogorithmModel = Algorithm(sequelize);
    

    那么你可以确保它是用

    创建的
    await AlogorithmModel.sync({ alter: true });
    

    我的用户模型文件是这样的:

    const { Model, DataTypes } = require('sequelize');
    module.exports = function(sequelize){
        class User extends Model {}
        return User.init({
          id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
          },
          name: {
              type: DataTypes.STRING,
              allowNull: false
          },
          trading_system_key: {
              type: DataTypes.STRING,
              allowNull: false
          },
        }, {
          sequelize,
          modelName: 'User',
          indexes: [{ unique: true, fields: ['trading_system_key'] }]
        });
    };
    

    【讨论】:

    • 我不知道该怎么做的一件事是控制 onUpdate 和 onDelete,如果有人知道,请告诉我
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2015-06-15
    • 1970-01-01
    • 2016-04-12
    • 2014-12-12
    • 1970-01-01
    • 2021-09-30
    相关资源
    最近更新 更多