Sunday, 16 April 2017

Sequelize: Many-to-many association with join table is using the incorrect field to find related items

Ran into a brickwall here:

Somehow, sequelize uses the primary key to find the related items on my many-to-many association even after explicitly defining the foreign key to use for my associations.

Can someone lend me a 2nd set of eyes to see where I'm getting this wrong?

What you are doing?

Querying with an include on a many-to-many association.

db.Alert
 .find({
  include: [{ model: db.AlertAction }],
  where: { AlertID: req.params.alertId }
 })

Here's my models:

Alert Model

export default (sequelize, DataTypes) => {
  const Alert = sequelize.define('Alert', {
    AlertID: {
      allowNull: false,
      type: DataTypes.BIGINT,
      primaryKey: true,
    },
    ActionGroupID: {
      allowNull: false,
      type: DataTypes.INTEGER,
    }, 
  }, {
    freezeTableName: true,
    classMethods: {
      associate(models) {
        Alert.belongsToMany(models.AlertAction, {
          through: {
            model: models.ActionGroup,
          },
          foreignKey: {
            name: 'ActionGroupID',
          },
        });
      },
    },
  });

  return Alert;
};

ActionGroup Model (Join Table)

export default (sequelize, DataTypes) => {
  const ActionGroup = sequelize.define('ActionGroup', {
    AlertActionID: {
      allowNull: false,
      type: DataTypes.INTEGER,
      primaryKey: true,
    },
    ActionGroupID: {
      allowNull: false,
      type: DataTypes.INTEGER,
      primaryKey: true,
    },
  }, {
    freezeTableName: true,
  });

  return ActionGroup;
};

AlertAction Model

export default (sequelize, DataTypes) => {
  const AlertAction = sequelize.define('AlertAction', {
    AlertActionID: {
      allowNull: false,
      primaryKey: true,
      type: DataTypes.INTEGER,
    },
  }, {
    freezeTableName: true,
    classMethods: {
      associate(models) {
        AlertAction.belongsToMany(models.Alert, {
          through: {
            model: models.ActionGroup,
          },
          foreignKey: {
            name: 'AlertActionID',
          },
        });
      },
    },
  });

  return AlertAction;
};

What do you expect to happen?

I have expected ActionGroupID is used to find related AlertActions.

[
  {
    "AlertID": "2",
    "ActionGroupID": 7,
    "AlertActions": [
      {
        "AlertActionID": 3,
        "AlertActionName": "Send to fill report",
        "ClientCode": "1008",
        "ActionGroup": {
          "ActionGroupID": 7,
          "AlertActionID": 3
        }
      }
    ]
  }
]

What is actually happening?

It uses the AlertID to find the associated AlertActions.

[
  {
    "AlertID": "2",
    "ActionGroupID": 7,
    "AlertActions": [
      {
        "AlertActionID": 1,
        "AlertActionName": "Zero inventory",
        "ClientCode": "1001",
        "ActionGroup": {
          "ActionGroupID": 2,
          "AlertActionID": 1
        }
      }
    ]
  }
]

Dialect: mssql Database version: Azure SQL Sequelize version: 3.30.4



via Dave

No comments:

Post a Comment