我正在尝试制作一个Sequelize查询,但它一直告诉我我的模型没有关联。然而,我确实宣布了一个协会......我想我根本不理解协会,而且我认为......
我制作了一个可以克隆的回购,以便自己查看问题:https://github.com/WaltzApp/sequelize-troubleshooting
我认为我遇到此问题的原因是Sequelize不支持复合外键,因此我必须在我的联接中使用自定义on
条款,但它不起作用正如所料,因为我无法在关联本身中指定相同的连接方法。这可以解释为什么我有时会通过Sequelize打印出功能完善的SQL,但查询仍然失败(大概是因为虽然数据库查询成功,但将结果转换为Sequelize entiteis失败)。
此复制工作的先前版本也会在下面复制:
相关模型
usersRoles :
module.exports = (sequelize, DataTypes) => {
const usersRoles = sequelize.define('usersRoles',
{
key: {
type: DataTypes.UUID,
primary: true,
},
userUid: {
type: DataTypes.UUID,
allowNull: false,
},
roleUid: {
type: DataTypes.UUID,
allowNull: false,
},
oemUid: {
type: DataTypes.UUID,
allowNull: true,
},
propertyManagerUid: {
type: DataTypes.UUID,
allowNull: true,
},
tenantUid: {
type: DataTypes.UUID,
allowNull: true,
},
[MORE FIELDS IRRELEVANT TO MY PROBLEM]
},
{
tableName: 'usersRoles',
indexes: [
{
name: 'userRoleOem',
fields: ['userUid', 'roleUid', 'oemUid'],
unique: true,
where: {
oemUid: { $ne: null },
propertyManagerUid: null,
tenantUid: null,
},
},
{
name: 'userRolePropertyManager',
fields: ['userUid', 'roleUid', 'propertyManagerUid'],
unique: true,
where: {
oemUid: null,
propertyManagerUid: { $ne: null },
tenantUid: null,
},
},
{
name: 'userRoleTenant',
fields: ['userUid', 'roleUid', 'tenantUid'],
unique: true,
where: {
oemUid: null,
propertyManagerUid: null,
tenantUid: { $ne: null },
},
},
{
name: 'compositePK',
fields: ['userUid', 'roleUid', 'oemUid', 'propertyManagerUid', 'tenantUid'],
unique: true,
},
],
freezeTableName: true,
timestamps: false,
});
usersRoles.removeAttribute('id');
usersRoles.associate = (models) => {
models.usersRoles.belongsTo(models.oems, { foreignKey: 'oemUid' });
models.usersRoles.belongsTo(models.propertyManagers, { foreignKey: 'propertyManagerUid' });
models.usersRoles.belongsTo(models.tenants, { foreignKey: 'tenantUid' });
models.usersRoles.belongsTo(models.users, { foreignKey: 'userUid' });
models.usersRoles.belongsTo(models.roles, { foreignKey: 'roleUid' });
models.usersRoles.belongsTo(models.invitations, { as: 'invitation', foreignKey: 'compositePK' });
};
return usersRoles;
};
邀请:
module.exports = (sequelize, DataTypes) => {
const invitations = sequelize.define('invitations',
{
uid: {
type: DataTypes.UUID,
primaryKey: true,
},
guestUid: {
type: DataTypes.UUID,
allowNull: true,
},
mappingGroupUid: {
type: DataTypes.UUID,
allowNull: true,
},
invitedByUid: {
type: DataTypes.UUID,
allowNull: false,
},
adminUid: {
type: DataTypes.UUID,
allowNull: true,
},
propertyManagerUid: {
type: DataTypes.UUID,
allowNull: true,
},
tenantUid: {
type: DataTypes.UUID,
allowNull: true,
},
[MORE FIELDS IRRELEVANT TO MY PROBLEM]
}, {
tableName: 'invitations',
freezeTableName: true,
timestamps: false,
});
invitations.associate = (models) => {
models.invitations.belongsTo(models.propertyManagers, { foreignKey: 'propertyManagerUid' });
models.invitations.belongsTo(models.tenants, { foreignKey: 'tenantUid' });
models.invitations.belongsTo(models.mappingGroups, { foreignKey: 'mappingGroupUid' });
models.invitations.belongsTo(models.users, { as: 'guest', foreignKey: 'guestUid' });
models.invitations.belongsTo(models.users, { as: 'invitedBy', foreignKey: 'invitedByUid' });
models.invitations.belongsTo(models.users, { as: 'admin', foreignKey: 'adminUid' });
models.invitations.hasMany(models.usersRoles, { as: 'invitation', foreignKey: 'compositePK' });
};
return invitations;
};
请注意,我将invitations
和usersRoles
模型与行models.invitations.hasMany(models.usersRoles, { foreignKey: 'compositePK' })
相关联。
查询
const path = require('path');
const glob = require('glob');
const Promise = require('bluebird');
const Sequelize = require('sequelize');
const configs = require('./test/_helpers/getConfigs');
const models = {};
const performQuery = (db) => {
const { usersRoles, invitations } = db; // eslint-disable-line max-len
const sql = {
include: {
model: invitations,
as: 'invitation',
on: {
user: Sequelize.where(
Sequelize.col('usersRoles.userUid'),
'=',
Sequelize.col('invitation.guestUid')),
propertyManager: Sequelize.where(
Sequelize.col('usersRoles.propertyManagerUid'),
'=',
Sequelize.col('invitation.propertyManagerUid')),
tenant: Sequelize.where(
Sequelize.col('usersRoles.tenantUid'),
'=',
Sequelize.col('invitation.tenantUid')),
},
},
};
return usersRoles.findAll(sql);
};
const sequelize = new Sequelize(
configs.get('DB_NAME'),
configs.get('DB_USER'),
configs.get('DB_PSSWD'),
{
dialect: configs.get('DB_TYPE'),
host: configs.get('DB_HOST'),
port: configs.get('DB_PORT'),
});
const modelsPath = path.join(__dirname, 'sequelize/models');
const globOpts = {
cwd: modelsPath,
ignore: '**/index.js',
realPath: false,
nosort: true,
nodir: true,
};
glob('**/*.js', globOpts, (err, files) => {
Promise.map(files, (file) => {
const model = sequelize.import(path.join(modelsPath, file));
models[model.name] = model;
})
.then(() => {
Object.keys(models).forEach((modelName) => {
if (models[modelName].associate) {
models[modelName].associate(models);
}
});
return performQuery(models);
})
.then((res) => {
console.log('SUCCESS', res);
}, (reason) => {
console.error('FAILED', reason);
});
});
输出
FAILED { SequelizeEagerLoadingError: invitations is not associated to usersRoles!
at Function._getIncludedAssociation (.../node_modules/sequelize/lib/model.js:573:13)
at Function._validateIncludedElement (.../node_modules/sequelize/lib/model.js:489:53)
at options.include.options.include.map.include (.../node_modules/sequelize/lib/model.js:385:37)
at Array.map (native)
at Function._validateIncludedElements (.../node_modules/sequelize/lib/model.js:381:39)
at Promise.try.then.then (.../node_modules/sequelize/lib/model.js:1525:14)
at tryCatcher (.../node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (.../node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (.../node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (.../node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (.../node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (.../node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (.../node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (.../node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:637:20)
at tryOnImmediate (timers.js:610:5)
at processImmediate [as _immediateCallback] (timers.js:582:5) name: 'SequelizeEagerLoadingError' }
进一步尝试 我尝试将以下行添加到邀请模型中:
models.usersRoles.belongsTo(models.invitations);
在这种情况下,Sequelize会打印一些SQL,这些SQL在执行时完全按预期工作,但显然它没有正确执行,因为查询仍然不起作用,而是说SequelizeDatabaseError: relation "usersRoles" does not exist
。
执行(默认):SELECT" usersRoles"。" key"," usersRoles"。" userUid", " usersRoles"。" roleUid"," usersRoles"。" oemUid", " usersRoles"。" propertyManagerUid"," usersRoles"。" doorSchedule", " usersRoles"。" cardId"," usersRoles"。" notifyBy", " usersRoles"。" contactEmail"," usersRoles"。" tenantUid", " usersRoles"。" createdAt"," usersRoles"。" compositePK", " usersRoles"。" invitationUid","邀请"。" uid" AS" invitation.uid", "邀请""状态" AS" invitation.status","邀请"。" guestUid" AS" invitation.guestUid","邀请"。" firstName"如 " invitation.firstName","邀请"。" lastName"如 " invitation.lastName","邀请"。"电子邮件" AS" invitation.email", "邀请""移动" AS" invitation.mobile", "邀请"" mappingGroupUid" AS" invitation.mappingGroupUid", "邀请"" doorSchedule" AS" invitation.doorSchedule", "邀请"" invitedByUid" AS" invitation.invitedByUid", "邀请"" adminUid" AS" invitation.adminUid", "邀请"" acceptedAt" AS" invitation.acceptedAt", "邀请"" rejectedAt" AS" invitation.rejectedAt", "邀请"" propertyManagerUid" AS" invitation.propertyManagerUid", "邀请"" tenantUid" AS" invitation.tenantUid", "邀请"" contactEmail" AS" invitation.contactEmail", "邀请"" notifyBy" AS" invitation.notifyBy", "邀请"" createdAt" AS" invitation.createdAt", "邀请"" updatedAt" AS" invitation.updatedAt"来自" usersRoles" AS" usersRoles" LEFT OUTER JOIN"邀请" AS"邀请"上 " usersRoles"" userUid" ="邀请"" guestUid"和 " usersRoles"" propertyManagerUid" ="邀请"" propertyManagerUid" AND" usersRoles"。" tenantUid" ="邀请"。" tenantUid&#34 ;;查询失败{ SequelizeDatabaseError:relation" usersRoles"不存在
答案 0 :(得分:0)
您永远不会调用Model.associate()
方法,因此模型不会相互关联。诀窍在于关联可能需要尚未定义的模型,因此关联者必须是最后的。模型加载后循环遍历它们并调用model.associate(models)
来创建关联。
userRole
定义也不包含与invitations
的关联。在Sequelize中,必须从要查询的一侧定义关系,或者如果您计划从两个对象查询关系,则必须同时定义关系。由于invitations
有很多userRoles
,我认为userRoles
属于invitations
。您在查询中将该表引用为invitation
,因此您可能希望将该关联别名为as
属性。
<强>的UserRole 强>
models.usersRoles.belongsTo(models.invitations, {
as: 'invitation',
foreignKey: 'compositePK',
});