[英]Sequelize Many-to-Many Association -- "Include" query error saying there is no association
我有两个模型,“用户”和“网站”。 每个用户可以有多个网站,每个网站可以有多个用户。
Users.associate = function(models) {
Users.belongsToMany(models.Websites, {
through: "UserWebsites",
as: 'Websites',
timestamps: false,
});
};
Websites.associate = function(models) {
Websites.belongsToMany(models.Users, {
through: "UserWebsites",
as: 'Users',
timestamps: false,
});
};
查询是:
let userId = req.params.id;
db.Users.findOne({
where: {
id: userId
},
include: [{ model: db.Websites }]
}).then(result => console.log(result));
我继续收到一个错误:
Unhandled rejection SequelizeEagerLoadingError: Websites is not associated to Users!
这很奇怪,因为 sequelize 还在 MySQL 中创建了一个“UserWebsites”表,显示关联在那里
它应该工作。 这是一个使用"sequelize": "^5.21.3"
的完整工作演示:
index.ts
:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
import assert from 'assert';
class Users extends Model {}
Users.init(
{
id: {
primaryKey: true,
autoIncrement: true,
allowNull: false,
type: DataTypes.INTEGER,
},
},
{ sequelize, modelName: 'Users' },
);
class Websites extends Model {}
Websites.init(
{
url: DataTypes.STRING,
},
{ sequelize, modelName: 'Websites' },
);
Users.belongsToMany(Websites, { through: 'UserWebsites', as: 'Websites', timestamps: false });
Websites.belongsToMany(Users, { through: 'UserWebsites', as: 'Users', timestamps: false });
(async function test() {
try {
await sequelize.sync({ force: true });
const websitesOfUser1 = [{ url: 'twitter' }, { url: 'stackoverflow' }];
const websitesOfUser2 = [{ url: 'github' }, { url: 'google' }];
// seed
await Users.bulkCreate(
[
{ id: 1, Websites: websitesOfUser1 },
{ id: 2, Websites: websitesOfUser2 },
],
{ include: [{ model: Websites, as: 'Websites' }] },
);
// test
const user = await Users.findOne({
where: { id: 1 },
include: [{ model: Websites, as: 'Websites' }],
});
assert.equal(user.Websites.length, websitesOfUser1.length, 'user 1 has two websites');
const websitesDataValues = user.Websites.map((website) => website.dataValues);
console.log('websitesDataValues: ', websitesDataValues);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
执行结果:
Executing (default): DROP TABLE IF EXISTS "UserWebsites" CASCADE;
Executing (default): DROP TABLE IF EXISTS "Websites" CASCADE;
Executing (default): DROP TABLE IF EXISTS "Users" CASCADE;
Executing (default): DROP TABLE IF EXISTS "Users" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Users" ("id" SERIAL , 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 = 'Users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "Websites" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Websites" ("id" SERIAL , "url" 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 = 'Websites' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "UserWebsites" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "UserWebsites" ("UserId" INTEGER REFERENCES "Users" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "WebsiteId" INTEGER REFERENCES "Websites" ("id") ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY ("UserId","WebsiteId"));
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 = 'UserWebsites' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "Users" ("id") VALUES (1),(2) RETURNING *;
Executing (default): INSERT INTO "Websites" ("id","url") VALUES (DEFAULT,'twitter'),(DEFAULT,'stackoverflow'),(DEFAULT,'github'),(DEFAULT,'google') RETURNING *;
Executing (default): INSERT INTO "UserWebsites" ("UserId","WebsiteId") VALUES (1,1),(1,2),(2,3),(2,4) RETURNING *;
Executing (default): SELECT "Users"."id", "Websites"."id" AS "Websites.id", "Websites"."url" AS "Websites.url", "Websites->UserWebsites"."UserId" AS "Websites.UserWebsites.UserId", "Websites->UserWebsites"."WebsiteId" AS "Websites.UserWebsites.WebsiteId" FROM "Users" AS "Users" LEFT OUTER JOIN ( "UserWebsites" AS "Websites->UserWebsites" INNER JOIN "Websites" AS "Websites" ON "Websites"."id" = "Websites->UserWebsites"."WebsiteId") ON "Users"."id" = "Websites->UserWebsites"."UserId" WHERE "Users"."id" = 1;
websitesDataValues: [ { id: 1,
url: 'twitter',
UserWebsites:
UserWebsites {
dataValues: [Object],
_previousDataValues: [Object],
_changed: {},
_modelOptions: [Object],
_options: [Object],
isNewRecord: false } },
{ id: 2,
url: 'stackoverflow',
UserWebsites:
UserWebsites {
dataValues: [Object],
_previousDataValues: [Object],
_changed: {},
_modelOptions: [Object],
_options: [Object],
isNewRecord: false } } ]
查看数据库中的数据记录:
node-sequelize-examples=# select * from "UserWebsites";
UserId | WebsiteId
--------+-----------
1 | 1
1 | 2
2 | 3
2 | 4
(4 rows)
node-sequelize-examples=# select * from "Websites";
id | url
----+---------------
1 | twitter
2 | stackoverflow
3 | github
4 | google
(4 rows)
node-sequelize-examples=# select * from "Users";
id
----
1
2
(2 rows)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.