Краткий ответ: вы должны добавить опцию foreignKey
для User.hasMany(Company)
ассоциации следующим образом:
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": "^5.21.3",
Исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60190182