如何在Sequelize中使用外键和常规键创建复合唯一约束?

时间:2017-07-13 21:00:09

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

我们有两个模型,用户和项目。在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',
    },
});

3 个答案:

答案 0 :(得分:1)

您可以使用迁移。

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

来自docs

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

答案 1 :(得分:1)

如果有人还在关注这个,我通过在需要唯一约束的模型中手动定义外键来解决这个问题(您仍然可以使用续集关联,例如 .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 内的外键定义的更多信息。

答案 2 :(得分:0)

就我而言,我根据 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'] }]
    });
};