Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique constraint across foreign keys in Sequelize model

Tags:

sequelize.js

I have a simple Sequelize model that is associated with other models.

module.exports = function (sequelize, DataTypes) {
  var Votes = sequelize.define('Votes', {
    isUpVote: DataTypes.BOOLEAN
  }, {
    classMethods: {
      associate: function (models) {
        Votes.belongsTo(models.Track);
        Votes.belongsTo(models.User);
      }
    }
  });

  return Votes;
}

Sequelize will generate a table with an id, TrackId, UserId and isUpVote.

I want to set a UNIQUE constraint across TrackId and UserId (i.e. a composite index ensuring that there is only one vote record for a given track and user).

How can this be done?

like image 411
Brad Avatar asked Apr 10 '15 01:04

Brad


2 Answers

you can use the unique constraint and give it a string rather than a bool. Then another other fields with the same string will become part of the same composite index.

i.e.:

module.exports = function (sequelize, DataTypes) {
   var Votes = sequelize.define('Votes', {
      isUpVote: {
          type: DataTypes.BOOLEAN,
          unique: 'myCompositeIndexName'
      },
      TrackId: {
          type: DataType.INTEGER
          unique: 'myCompositeIndexName',
      },
      UserId: {
          type: DataType.INTEGER
          unique: 'myCompositeIndexName',
      }
   }, {
       classMethods: {
           associate: function (models) {
               Votes.belongsTo(models.Track);
               Votes.belongsTo(models.User);
           }
       }
    });

    return Votes;
}

(^Not tested, just off the top of my head!)

The problem with this is that this will only occur during the creation of a table. If you table already exists, you can achieve this by using the migrations feature of sequelize-cli.

I really hope this helps else at least points you in the right direction. If you are still stuck, I recommend you go to the IRC channel for sequelize as it seems to be pretty active.

like image 142
swifty Avatar answered Sep 24 '22 02:09

swifty


What ended up working for me was adding it under indexes, e.g.:

module.exports = function (sequelize, DataTypes) {
  var Votes = sequelize.define('Votes', {
    isUpVote: DataTypes.BOOLEAN,
  }, {
    indexes: [
      {
        unique: true,
        fields: ['TrackId', 'UserId'],
      },
    ],
    classMethods: {
      associate: function (models) {
        Votes.belongsTo(models.Track);
        Votes.belongsTo(models.User);
      },
    },
  });

  return Votes;
}
like image 45
Tomty Avatar answered Sep 22 '22 02:09

Tomty