![](/img/trans.png)
[英]Sequelize Error: Include unexpected. Element has to be either a Model, an Association or an object
[英]Sequelize.js: Include unexpected. Element has to be either a Model, an Association or an object
我在我的 Node.js 应用程序中使用 Sequelize.js 并不断遇到一个非常奇怪的问题。
背景:我有两个模型, Account和AccountCategory ,如下所示。 我的 API 端点调用路由/accounts
调用帐户控制器来执行Account.findAll()
查询。
Accounts模型有一个defaultScope
以默认包含相关类别,而不必每次都在findAll({})
块中指定它。
问题:当Accounts模型试图访问并返回数据库中的数据时, defaultScope
试图包含AccountCategory ,Sequelize 抛出错误:
包括意外。 元素必须是模型、关联或对象。
我怀疑这与在设置模型时AccountCategory放在我的模型文件夹中的Account之后的事实有关,因此未处理(关联)。 我基于这样一个事实,即用户和角色(即用户具有角色)等其他关联可以使用相同的方法(即,路径深度没有问题,正如这个答案所暗示的那样)。
在过去的 2 天里,我一直试图让defaultScope
正常工作并停止产生这个错误,但没有任何运气。 类似的问题没有提供答案,我将非常感谢解决此问题的任何帮助。 谢谢。
帐户:
module.exports = (sequelize, DataTypes) => {
const Account = sequelize.define(
"Account",
{
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(100)
},
category_id: {
type: DataTypes.INTEGER(11),
allowNull: false
}
},
{
timestamps: false,
tableName: "Account",
defaultScope: {
include: [{
model: sequelize.models.AccountCategory,
as: "category"
}]
}
}
);
Account.associate = models => {
// Association: Account -> AccountCategory
Account.belongsTo(models.AccountCategory, {
onDelete: "CASCADE",
foreignKey: {
fieldName: "category_id",
allowNull: false,
require: true
},
targetKey: "id",
as: "category"
});
};
return Account;
};
账户类别:
module.exports = (sequelize, DataTypes) => {
var AccountCategory = sequelize.define(
"AccountCategory",
{
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(30),
allowNull: false,
unique: true
}
},
{
timestamps: false,
tableName: "Account_Category"
}
);
return AccountCategory;
};
型号索引:
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 db = {};
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASS,
{
host: process.env.DB_HOST,
dialect: "mysql",
operatorAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
fs.readdirSync(__dirname)
.filter(function(file) {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach(function(file) {
var model = sequelize["import"](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if (db[modelName].associate) {
db[modelName].associate(db);
}
db[modelName].associate(db);
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
您应该尝试通过别名定义包含
defaultScope: {
include: 'category'
}
连续为我工作5+
当你说:
我怀疑这与在设置模型时 AccountCategory 放在我的模型文件夹中的 Account 之后的事实有关,因此未处理(关联)。
TLDR:在模型类定义中添加一个类似于associate
函数的新函数,并使用addScope函数定义引用其他模型的任何作用域,这些模型可能由于文件树顺序而未初始化。 最后,以与在models.index.js
文件中调用db[modelName].associate
相同的方式调用该新函数。
我有一个类似的问题,并通过定义引用任何模型的任何范围来解决它,例如在include
中,在所有模型在您的models/index.js
文件中运行以下内容后初始化之后。
这是一个例子:
模型/agent.js
'use strict';
const { Model } = require('sequelize');
const camelCase = require('lodash/camelCase');
const { permissionNames } = require('../../api/constants/permissions');
module.exports = (sequelize, DataTypes) => {
/**
* @summary Agent model
*/
class Agent extends Model {}
Agent.init(
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
scopes: {
// Works because the agent-role.js file / model comes before agent.js in the file tree
[camelCase(permissionNames.readAgentRoles)]: {
include: [
{
model: sequelize.models.AgentRole,
},
],
},
// Doesn't work due to import order in models/index.js, i.e., agent.js is before role.js in the file tree
// [camelCase(permissionNames.readRoles)]: {
// include: [
// {
// model: sequelize.models.Role,
// },
// ],
// },
},
}
);
Agent.associate = function (models) {
Agent.belongsToMany(models.Role, {
through: 'AgentRole',
onDelete: 'CASCADE', // default for belongsToMany
onUpdate: 'CASCADE', // default for belongsToMany
foreignKey: {
name: 'agentId',
type: DataTypes.INTEGER,
allowNull: false,
},
});
Agent.hasMany(models.AgentRole, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
foreignKey: {
name: 'agentId',
type: DataTypes.INTEGER,
allowNull: false,
},
});
};
// Add a custom `addScopes` function to call after initializing all models in `index.js`
Agent.addScopes = function (models) {
Agent.addScope(camelCase(permissionNames.readRoles), {
include: [
{
model: models.Role,
},
],
});
};
return Agent;
};
模型/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const config = require('../database-config.js');
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
/**
* Import and attach all of the model definitions within this 'models' directory to the sequelize instance.
*/
fs.readdirSync(__dirname)
.filter((file) => {
return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js';
})
.forEach((file) => {
// Here is where file tree order matters... the sequelize const may not have the required model added to it yet
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);
}
// We need to add scopes that reference other tables once they have all been initialized
if (db[modelName].addScopes) {
db[modelName].addScopes(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.