Sequelize Association Error: A is not associated to B

Sequelize Association Error: A is not associated to B

我正在为我的 Postgres 数据库使用 Sequelize。我有一个消息和一个用户 table;一个用户有很多条消息,一条消息属于一个用户。我将我的模型定义如下:

用户

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    firstName: {
      type: DataTypes.STRING,
      allowNull: false
    },
    lastName: {
      type: DataTypes.STRING,
      allowNull: false
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isEmail: true,
      }
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        len: [8, 50],
      }
    },
  }, {
    modelName: 'User',
  });

  User.associate = (models) => {
    User.hasMany(models.Message, { foreignKey: 'userId', as: 'Messages' })
  }

  return User;
};

留言

module.exports = (sequelize, DataTypes) => {
    const Message = sequelize.define('Message', {
        content: {
            allowNull: false,
            type: DataTypes.STRING,
            validate: {
                len: [1, 248],
            }
        },
        userId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'Users',
                key: 'id'
            }
        },
        likes: {
            defaultValue: 0,
            type: DataTypes.INTEGER
        },
    }, {
        modelName: 'Message',
    });

    Message.associate = (models) => {
        Message.belongsTo(models.User, { foreignKey: 'userId', as: 'User', onDelete: 'CASCADE' })
    }

    return Message;
};

下面是我测试它们的方式:

User.create({
    firstName: 'Test', lastName: 'Test', email: 'test@test.com', password: '87654321'
}).then((newUser) => {
    console.log(newUser.get())
})

Message.bulkCreate([
    { content: "Hello", likes: 0, userId: 1 },
    { content: "Hello World", likes: 0, userId: 1 },
    { content: "Hello World 2", likes: 123, userId: 1 }
])
    .then((newMessages) => {
        console.log(newMessages)
    })

const findAllWithMessages = async () => {
    const users = await User.findAll({
        include: [{
            model: Message
        }]
    });
    console.log(JSON.stringify(users, null));
}

这是我创建用户的迁移文件 table:

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstName: {
        type: Sequelize.STRING,
        allowNull: false
      },
      lastName: {
        type: Sequelize.STRING,
        allowNull: false
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false,
        unique: true,
        validate: {
          isEmail: true,
        }
      },
      password: {
        type: Sequelize.STRING,
        allowNull: false,
        validate: {
          len: [8, 50],
        }
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Users');
  }
};

以及消息 table:

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('Messages', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      userId: {
        type: Sequelize.INTEGER,
        allowNull: false,
        references: {
          model: 'Users',
          key: 'id',
          as: 'userId',
        },
        onUpdate: 'CASCADE',
        onDelete: 'SET NULL',
      },
      content: {
        allowNull: false,
        type: Sequelize.STRING,
        validate: {
          len: [1, 248],
        }
      },
      likes: {
        defaultValue: 0,
        type: Sequelize.INTEGER
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Messages');
  }
};

当您 运行 sequelize-cli init:

时,我正在使用开箱即用的 Sequelize CLI 注册我的模型和关联
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];

const db = {};

let sequelize;
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 = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
    db[model.name] = model;
  });

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

const User = require('./user')(sequelize, Sequelize.DataTypes)
const Message = require('./message')(sequelize, Sequelize.DataTypes)

db.models = { User, Message }
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.DataTypes = Sequelize.DataTypes

module.exports = db;

最后,当我 运行 findAllWithMessages() 时,我得到了这个错误 UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: Message is not associated to User!

我可以确认正在创建模型并且模型之间的关联有效,因为当我 运行 原始 SQL 查询 select * from "Messages" as a inner join "Users" as b on b.id = a."userId" where a."userId"=1; 时,我得到了正确的结果。所以我假设它是一个续集的东西。

感谢任何帮助!

我找到了我的问题。在我从 db.models = { User, Message } 导入的代码中,这个块 Object.keys(db).forEach(modelName)... 没有关联我正在使用的模型。本质上,我是在与我使用的实例不同的模型实例上调用 .associate 函数。