【问题标题】:Helper methods and associations with include not working on sequelize辅助方法和关联包括不处理 sequelize
【发布时间】:2017-07-27 02:06:46
【问题描述】:

在使用 belongsTo/hasMany 时,我无法调用应该由 sequelize 生成的辅助方法。而且我不能急于加载一张桌子。 当尝试运行辅助方法时,我收到一条消息说没有这样的方法,当尝试使用 findAll 并包含传递另一个表时,它说这些表没有关联,请参阅下面的详细信息:

模型目录:

./models
--ticket.js
--category.js
--index.js

ticket.js

'use strict';

module.exports = function(sequelize, DataTypes) {
  var Ticket = sequelize.define('Ticket', {
    // category_id: DataTypes.INTEGER,
    subject: DataTypes.STRING,
    description: DataTypes.TEXT,
    requester_name: DataTypes.STRING,
    requester_email: DataTypes.STRING,
    owner_email: DataTypes.STRING,
    status: {
      type: DataTypes.ENUM,
      values: ['opened', 'in progress', 'closed']
    }
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // associations can be defined here
        Ticket.belongsTo(models['Category']);
        Ticket.hasMany(models['Interaction']);
      }
    }
  });

  return Ticket;
};

category.js

'use strict';

module.exports = function(sequelize, DataTypes) {
  var Category = sequelize.define('Category', {
    name: DataTypes.STRING
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // associations can be defined here
        Category.hasMany(models['Ticket']);
      }
    }
  });
  return Category;
};

index.js

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var env       = process.env.NODE_ENV || 'development';
var config    = require(__dirname + '/../config/config.json')[env];
var db        = {};

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

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.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

然后我为模型创建常量:

const models = require('../models'),
    Ticket = models['Ticket'],
    Category = models['Category'];

尝试调用 Ticket.getCategory() 时,如下所示:

Ticket.findById(req.params.ticket_id).then((ticket) => {
        ticket.getCategory().then((category)=>{
            ticket['category'] = category;
            res.json(ticket);
        });
    });

我明白了:

Executing (default): SELECT `id`, `subject`, `description`, `requester_name`, `requester_email`, `owner_email`, `status`, `created_at`, `updated_at` FROM `Tickets` AS `Ticket` WHERE `Ticket`.`id` = '1';
Unhandled rejection TypeError: ticket.getCategory is not a function

如果我尝试使用预先加载,如下所示:

Ticket.findAll({where:{id:req.params.ticket_id},include:[Category]}).then((ticket) => {
    res.json(ticket);
});

我明白了:

Unhandled rejection SequelizeEagerLoadingError: Category is not associated to Ticket!

我做错了什么?

提前致谢!

【问题讨论】:

  • 你的sequelize版本是什么?
  • "sequelize": "^4.2.0", "sequelize-cli": "^2.7.0",

标签: mysql node.js sequelize.js


【解决方案1】:

正如您所说,您使用的是 seqielize ^4.2.0,这是主要更新 API 几乎没有变化。'

在版本 4 中,您不应该通过 classMethods 对象添加类方法,而是应该这样做。

var Ticket = sequelize.define('Ticket', {
    // category_id: DataTypes.INTEGER,
    subject: DataTypes.STRING,
    description: DataTypes.TEXT,
    requester_name: DataTypes.STRING,
    requester_email: DataTypes.STRING,
    owner_email: DataTypes.STRING,
    status: {
      type: DataTypes.ENUM,
      values: ['opened', 'in progress', 'closed']
    }
  }, {
    underscored: true,
});

Ticket.associate = function(models) {
    // associations can be defined here
    Ticket.belongsTo(models['Category']);
    Ticket.hasMany(models['Interaction']);
};

您可以阅读如何从 sequelize 3 升级到 4 here

【讨论】:

  • 谢谢阿伦!几个小时前,我在查看他们的 nodejs-example 时解决了这个问题,花了我一些时间思考这个问题,来到这里回答并找到了你的答案。这解决了问题!不知道从 3 到 4 的变化,谢谢!
  • 欢迎先生!很高兴对您有所帮助。
【解决方案2】:

问题是您的关联还没有完全完成。您需要指定一个外键。例如:

module.exports = function(sequelize, DataTypes) {
  var Ticket = sequelize.define('Ticket', {
    //blablabla
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // here specify which are your foreign keys
        // category_id is just to illustrate
        Ticket.belongsTo(models['Category'], {foreignKey: category_id});
        Ticket.hasMany(models['Interaction'], {foreignKey: something_id});
      }
    }
  });

  return Ticket;
};

在这种情况下,这也需要在对应的类别和交互中完成。然后你就可以使用sequelize魔法了

【讨论】:

  • 感谢您的快速响应。我已经读过这是默认的foreignKey,但只是为了确保我已经添加了它,但得到了相同的结果。如您所见,我已经在类别 (hasMany) 和票证 (belongsTo) 上创建了关联。 foreignKey 应该只添加到 belongsTo 关联,对吗?请忽略交互关联。
  • 我总是以两种方式添加它们(belongsTo 和 hasMany)。不知道是不是强制性的。另外,你定义了这个领域吗?在您的票证定义中,您有主题、描述等,但我没有看到定义的 category_id。可能是这个问题吗?
猜你喜欢
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 2017-10-17
  • 2018-05-15
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
相关资源
最近更新 更多