Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize Eager Loading Error when including related model

I'm using Sequelize to make this request:

return Expense.findAll({
     include: [{
       model: ExpenseCategory
     }],
   })
  .then(expenses => res.status(200).send(expenses))
  .catch(error => res.status(500).send({ error: error }));

and I'm getting this error:

SequelizeEagerLoadingError

I can't seem to find my error.
This are my migrations for the three models (User, Expense, ExpenseCategory):

queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      email: {
        allowNull: false,
        type: Sequelize.STRING,
        unique: true
      },
      passhash: {
        allowNull: false,
        type: Sequelize.STRING
      },
      currency: {
        type: Sequelize.STRING,
        defualt: 'lev'
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });



queryInterface.createTable('Expenses', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      value: {
        allowNull: false,
        type: Sequelize.FLOAT
      },
      text: {
        type: Sequelize.STRING
      },
      expenseCategoryId: {
        allowNull: false,
        type: Sequelize.INTEGER,
        references: {
          model: 'ExpenseCategories',
          key: 'id'
        },
        onDelete: 'cascade'
      },
      userId: {
        allowNull: false,
        type: Sequelize.INTEGER,
        references: {
          model: 'Users',
          key: 'id'
        },
        onDelete: 'cascade'
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });

queryInterface.createTable('ExpenseCategories', {
        id: {
          allowNull: false,
          autoIncrement: true,
          primaryKey: true,
          type: Sequelize.INTEGER
        },
        category: {
          allowNull: false,
          type: Sequelize.STRING
        },
        createdAt: {
          allowNull: false,
          type: Sequelize.DATE
        },
        updatedAt: {
          allowNull: false,
          type: Sequelize.DATE
        }
      });

and the model definitions:

  const User = sequelize.define('User', {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    email: {
      allowNull: false,
      type: DataTypes.STRING,
      unique: true
    },
    passhash: {
      allowNull: false,
      type: DataTypes.STRING
    },
    currency: {
      type: DataTypes.STRING,
      defaultValue: 'lev'
    }
  }, {
    classMethods: {
      associate: function (models) {
        User.hasMany(models.Income, {
          foreignKey: 'userId',
        });
        User.hasMany(models.Expense, {
          foreignKey: 'userId',
        });
      }
    }
  });

const Expense = sequelize.define('Expense', {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    value: {
      allowNull: false,
      type: DataTypes.FLOAT
    },
    text: {
      type: DataTypes.STRING
    },
    expenseCategoryId: {
      allowNull: false,
      type: DataTypes.INTEGER
    },
    userId: {
      allowNull: false,
      type: DataTypes.INTEGER
    }
  }, {
    classMethods: {
      associate: function (models) {
        Expense.belongsTo(models.User, {
          foreignKey: 'userId'
        });
        Expense.belongsTo(models.ExpenseCateogory, {
          foreignKey: 'expenseCateogoryId',
        });
      }
    }
  });

const ExpenseCategory = sequelize.define('ExpenseCategory', {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    category: {
      allowNull: false,
      type: DataTypes.STRING
    }
  }, {
    classMethods: {
      associate: function (models) {
        ExpenseCateogory.hasMany(models.Expense, {
          foreignKey: 'expenseCategoryId'
        });
      }
    }
  });
like image 748
es.16 Avatar asked Jul 04 '17 19:07

es.16


1 Answers

I got an working answer. In this example i have a scheme where a department can have a lot of positions. The Position will include the department and the department will include its positions.

models/Department.js

module.exports = (sequelize, DataTypes) => 
{
const Sequelize = require('sequelize');
const Department = sequelize.define('Department', 
{
    ...
}
Department.associate = function(models) {
    Department.hasMany(models.Position, {
      foreignKey: 'department_id',
      as: 'positions'
    });
};

return Department;
};

models/Position.js

module.exports = (sequelize, DataTypes) => 
{
const Sequelize = require('sequelize');
const Position = sequelize.define('Position', 
{
    ...
}

Position.associate = function(models) {
    Position.belongsTo(models.Department, {
        foreignKey: 'department_id',
        as: 'department',
        onDelete: 'CASCADE'
    });
};

return Position;
};

controllers/departmentController.js

exports.all = async function(req, res)
{
return Department
    .findAll({include: [ 'positions' ]})
    .then((data) => {
        if (!data) { return res.status(400).json({status: 400,message: 'Registro não encontrado', data: data }); }
        return res.status(200).json(data);
    })
    .catch((error) => {
        return res.status(400).json({message: 'Falha no banco de dados.', data: error})
    });
};

controllers/positionController.js

exports.all = async function(req, res)
{
return Position
    .findAll({include: [ 'department' ]})
    .then((data) => {
        if (!data) { return res.status(400).json({status: 400,message: 'Registro não encontrado', data: data }); }
        return res.status(200).json(data);
    })
    .catch((error) => {
        console.log(error);
        return res.status(400).json({message: 'Falha no banco de dados.', data: error})
    });
};
like image 97
heavyrick Avatar answered Oct 05 '22 04:10

heavyrick