10

I have a model called Task, which can have many parent tasks (multiple ancestors) and/or child tasks.

If I were to model this without Sequelize, I'd have a table called ParentTasks, which would have a ParentTaskId and a TaskId to determine the relationship and a Tasks table with an id as the primary key.

Using Sequelize, is this possible? I've tried so many different permutations and combinations, but none lead to what I want.

Any help would be appreciated.

Thanks.

Shamoon
  • 41,293
  • 91
  • 306
  • 570
  • Can you give me a code example? – Shamoon Sep 01 '14 at 18:31
  • 1
    When I open the given link there are lots of code examples on that page. Maybe YOU need to give any code example(s) of the code that is not working for you. It seems you ask a generic question, but have a very specific one in mind. I guess, most people at stackoverflow are not good at mind reading. – Quicker Sep 02 '14 at 06:55
  • @Quicker You should usually post that here in case the page 404s. Which is has. – Noah Apr 08 '16 at 22:52
  • @Noah: 1,5 year the link was outdated - I deleted that comment with the link; just for others: there were/are those informaton at sequelizejs.com (use g***) – Quicker Apr 15 '16 at 09:44

2 Answers2

17

What have you tried?

How about this:

var Task = sequelize.define('Task', {
  name: Sequelize.STRING
});

Task.belongsToMany(Task, { as: 'children', foreignKey: 'ParentTaskId', through: 'ParentTasks' });
Task.belongsToMany(Task, { as: 'parents', foreignKey: 'TaskId', through: 'ParentTasks' });

please refer to https://sequelize.org/master/class/lib/associations/belongs-to-many.js~BelongsToMany.html

adnan shuja
  • 183
  • 1
  • 2
  • 7
LarsJK
  • 2,196
  • 18
  • 23
  • 13
    Hey, looks like the answer is out of date... I'm getting the following error: N:M associations are not supported with hasMany. Use belongsToMany instead – Asaf May 16 '16 at 08:26
9

According to Asaf in above comment, hasMany no longer works. Here is a solution using belongsToMany:

User model:

module.exports = (sequelize, DataTypes) => {
  const Users = sequelize.define('Users', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      allowNull: false,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false
    }
  }, {
    freezeTableName: true
  });

  Users.associate = function(models) {
    Users.belongsToMany(models.Users, { through: models.UserUsers, as: 'Parents', foreignKey: 'parentId' });
    Users.belongsToMany(models.Users, { through: models.UserUsers, as: 'Siblings', foreignKey: 'siblingId' });
  };

  return Users;
};

UserUsers model:

module.exports = (sequelize, DataTypes) => {
  const UserUsers = sequelize.define('UserUsers', {
  }, {
    freezeTableName: true
  });

  UserUsers.associate = function(models) {
    UserUsers.belongsTo(models.Users, { as: 'Parent', onDelete: 'CASCADE'});
    UserUsers.belongsTo(models.Users, { as: 'Sibling', onDelete: 'CASCADE' });
  };

  return UserUsers;
};

Using this you set and get like this:

models.Users.findOne({ where: { name: 'name' } })
.then(u1 => {
  models.Users.findOne({ where: { name: 'name2'} })
  .then(u2 => {
    u2.addSibling(u1);
    // or if you have a list of siblings you can use the function:
    u2.addSiblings([u1, ...more siblings]);
  });
});

and

models.Users.findOne({ where: { name: 'name'} })
.then(person => {
  person.getSiblings()
  .then(siblings => { console.log(siblings) });
});

References: Sequelize docs

Freece
  • 454
  • 5
  • 11