javascript - Sequelize hasMany 和belongsTo 问题

标签 javascript mysql node.js orm sequelize.js

我将使用node.js 和sequelize.js 在Mysql 中创建2 个表。

我有 2 个模型 - UserCompany

用户有以下字段 - ID - 用户名 - 密码

公司有以下字段 - ID - 姓名 -owner_id(这是User中id的外键,不是主键)

User模型中,我添加了以下代码。

User.hasMany(Company)

Company模型中,我添加了以下代码。

Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });

现在,问题是在 companies 表中,我可以看到有 2 列 - owner_idUser_id

有什么办法可以不在sequelize选项中添加User_id吗?

最佳答案

简短回答:您应该为 User.hasMany(Company) 关联添加 foreignKey 选项,如下所示:

User.hasMany(Company, { foreignKey: 'owner_id' });
Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });

很长的答案,这里是完成的工作演示和一些简单的测试:

index.ts:

import { sequelize } from '../../db';
import { Model, DataTypes, HasManyGetAssociationsMixin, BelongsToGetAssociationMixin } from 'sequelize';
import assert from 'assert';

class User extends Model {
  public id!: number;
  public username!: string;
  public password!: string;
  public getCompanies!: HasManyGetAssociationsMixin<Company>;
}
User.init(
  {
    username: DataTypes.STRING,
    password: DataTypes.STRING,
  },
  { sequelize, modelName: 'User', underscored: true },
);

class Company extends Model {
  public id!: number;
  public name!: string;
  public owner_id!: number;
  public getOwner!: BelongsToGetAssociationMixin<User>;
}
Company.init({ name: DataTypes.STRING }, { sequelize, modelName: 'Company', underscored: true });

User.hasMany(Company, { foreignKey: 'owner_id' });
Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });

(async function test() {
  try {
    await sequelize.sync({ force: true });
    // seed
    await User.create(
      { username: 'jenifer', password: '123', Companies: [{ name: 'Google' }, { name: 'Twitter' }] },
      { include: [Company] },
    );
    // assertion testing
    const user: User = await User.findByPk(1);
    assert(user.username === 'jenifer', 'The user should be jenifer');
    const companies: Company[] = await user.getCompanies();
    assert(companies.length === 2, 'The count of companies of jenifer should be 2');
    const company1 = companies[0];
    assert(typeof company1['User_id'] === 'undefined', 'User_id column should not be added to company model');
    const owner = await company1.getOwner();
    assert(owner.username === user.username);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

数据库中的数据记录:

node-sequelize-examples=# select * from "User";
 id | username | password
----+----------+----------
  1 | jenifer  | 123
(1 row)

node-sequelize-examples=# select * from "Company";
 id |  name   | owner_id
----+---------+----------
  1 | Google  |        1
  2 | Twitter |        1
(2 rows)

上述代码在没有断言失败的情况下的执行结果:

{ POSTGRES_HOST: '127.0.0.1',
  POSTGRES_PORT: '5430',
  POSTGRES_PASSWORD: 'testpass',
  POSTGRES_USER: 'testuser',
  POSTGRES_DB: 'node-sequelize-examples' }
Executing (default): DROP TABLE IF EXISTS "Company" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "User" ("id"   SERIAL , "username" VARCHAR(255), "password" VARCHAR(255), PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'User' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "Company" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Company" ("id"   SERIAL , "name" VARCHAR(255), "owner_id" INTEGER REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'Company' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "User" ("id","username","password") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "Company" ("id","name","owner_id") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "Company" ("id","name","owner_id") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): SELECT "id", "username", "password" FROM "User" AS "User" WHERE "User"."id" = 1;
Executing (default): SELECT "id", "name", "owner_id" FROM "Company" AS "Company" WHERE "Company"."owner_id" = 1;
Executing (default): SELECT "id", "username", "password" FROM "User" AS "User" WHERE "User"."id" = 1;

Sequelize 版本:

"sequelize": "^5.21.3",

源代码:https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60190182

关于javascript - Sequelize hasMany 和belongsTo 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60190182/

相关文章:

javascript - Screeps 很少有错误/问题

mysql - 安装 "Empty value for ' 端口时出现 phpmyadmin 错误。”

javascript - 如何在 node.js 中存储和修改大型数据集?

javascript - 刷新页面时阻止 safari 显示未保存的表单提示

javascript - Excel 和 IE7 - 防止 IE 打开 Excel 文件

javascript - Safari JavaScript 问题

mysql - 连接两个表并具有时间差的计数、非重复和平均值

mysql - 我应该为我的 MySQL 数据库使用 MyISAM 还是 InnoDB 表?

node.js - 如何在 bodyparser 之前访问请求的原始主体?

node.js - 源代码控制 (git) docker-compose.yml