node.js - Sequelize 关联错误 : A is not associated to B

标签 node.js postgresql sequelize.js associations

我在 Postgres 数据库中使用 Sequelize。我有一个 Messages 和一个 Users 表;一个用户有很多条消息,一条消息属于一个用户。我已经定义了我的模型如下:
用户

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));
}
这是我创建用户表的迁移文件:
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');
  }
};
和消息表:
'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; 时,我得到了正确的结果。所以我假设它是一个 Sequelize 的东西。
任何帮助表示赞赏!

最佳答案

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

关于node.js - Sequelize 关联错误 : A is not associated to B,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67358857/

相关文章:

sequelize.js - sequelize parseint INTEGER

sql - 从 Postgres 中的日期中提取工作日、毫秒、微秒、纳秒

postgresql - 在 Postgres 中删除一个被另一个引用的表

postgresql - (Postgres) row_number OVER 分区在 8.2

node.js - 在 Angular2 中导入模块

javascript - 有没有办法限制使用 sequelize select 查询返回的小数位数?

node.js - Sequelize 生成错误的查询? Sequelize 自动 ts 和 Sequelize

javascript - 如何使用webpack更新jade中的script标签?

node.js - 在 sails 中调试时监听 EADDRINUSE 错误

javascript - 如何使用 node.js 和 bash 脚本运行 javascript 文件?