node.jssequelize.js

Where to define sequelize associations


I'm using sequelize in my Node js app. All of the models are defined in separate files named, for instance, user.js, message.js and so on. I also have the index.js file that's auto-generated, here's a snippet of it, you'll probably recognize it:

if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

So I'm looking at the associations manual of sequelize here. The thing I can't figure out is where this would go in my case, since I'm using the auto-generated index.js file which gathers all the models. In their example, as you can see on the link, they've got something like:

const A = sequelize.define('A', /* ... */);
const B = sequelize.define('B', /* ... */);

A.hasOne(B); // A HasOne B
A.belongsTo(B); // A BelongsTo B
A.hasMany(B); // A HasMany B
A.belongsToMany(B, { through: 'C' }); 

How would I do the same thing when my models are spread across multiple files? I've tried something like this (for instance, in the message model):

  return sequelize.define('message', {
    message_id: {
      type: DataTypes.BIGINT,
      allowNull: false,
      autoIncrement:true,
      primaryKey: true
    },
    user_id: {
      type: DataTypes.BIGINT,
      allowNull: true
    }
    // and other stuff..
  }, {
    tableName: 'message'
  }).hasOne(require('./user'));
};

which gives an error: message.hasOne called with something that's not a subclass of Sequelize.Model

Any ideas?

Thanks.


Solution

  • Here's how I do it:

    module.exports = (sequelize, DataTypes) => {
      const MyEntity = sequelize.define(
        'MyEntity',
        {
          name: DataTypes.STRING
        },
        {}
      );
      MyEntity.associate = function(models) {
        // associations can be defined here
        MyEntity.hasMany(models.OtherEntity, {
          foreignKey: 'myEntityId',
          as: 'myEntities'
        });
      };
      return MyEntity;
    };