Sequelize:尝试嵌套关联时出错

Sequelize: Error trying to nested association

你好,我是 Sequelize 的新手,我真的不知道如何管理关系。我想设置 1:N 关系,但是当我看到结果时,我没有收到关系数据。我目前正在使用 2 个 table,medicoshospitals,其中 hospitals 可以有多个 doctors,但 doctors 只有一个hospital

这是我的 doctors table: models/doctors.js

    module.exports = function(sequelize, DataTypes) {
      return sequelize.define('doctors', {
        id: {
          type: DataTypes.INTEGER(11),
          allowNull: false,
          primaryKey: true,
          autoIncrement: true
        },
        name: {
          type: DataTypes.STRING,
          allowNull: false
        },
        lastName: {
          type: DataTypes.STRING,
          allowNull: false
        },
        SSN: {
          type: DataTypes.STRING,
          allowNull: false
        },
        speciality: {
          type: DataTypes.ENUM('Doctor','Geriatrician'),
          allowNull: false
        },
        idHospital: {
          type: DataTypes.INTEGER(11),
          allowNull: false,
        },
      }, {
        tableName: 'doctors',
        freezeTableName: true,
        classMethods: {
          associate: models =>  {
            models.doctors.belongsTo(models.hospitals,  {
              foreignKey: "idHospital"
            })
         }
       }
  });
      });
    };

这一个是 hospitals 一个:models/hospitals.js

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('hospitals', {
    id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    idData: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      references: {
        model: 'data',
        key: 'id'
      }
    },
  }, {
    tableName: 'hospitals',
    freezeTableName: true,
    classMethods: {
      associate: models =>  {
      models.hospitals.hasMany(models.doctors,  {
         foreignKey: "idHospital"
      })
    }
  }
  });
};

我用这个文件管理我的模型models/index.js

'use strict'

module.exports = (connection) => {
  const Users                     = connection.import('users'),
        States                    = connection.import('states'),
        Cities                    = connection.import('cities'),
        Data                      = connection.import('data'),
        Patient                   = connection.import('patients'),
        Hospitals                 = connection.import('hospitals'),
        Doctors                   = connection.import('doctors'),


        Doctors.belongsTo(Hospitals)
        Hospitals.hasMany(Doctors)
        require('../controllers/patients')(Users)
        require('../controllers/personal')(Doctors, Hospitals)
}

这是我的controller/controllers/personal.js

'use strict'

module.exports = (Doctors) =>  {

  const express   = require('express'),
        router    = express.Router()
  router
  .get('/', (req, res) => {
    Doctors.findAll({ include: [{ model: Hospitals, include: [Doctors], }], }).then((Doctors) => console.log(Doctors));
  })

和我的主要 index

'use strict'

const express       = require('express'),
      path          = require('path'),
      bodyParser    = require('body-parser'),
      Sequelize     = require('sequelize'),
      port          = process.env.PORT || 3000,
      app           = express(),
      connection    = new Sequelize('Matadero', 'root', 'root');

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:true}))

app.set('view engine', 'ejs')
app.set('views', path.resolve(__dirname, 'client', 'views'))

app.use(express.static(path.resolve(__dirname, 'client')))

app.get('/', (req, res) =>  {
  res.render('admin/index.ejs')
})

const onListening = () => console.log(`Successful connection at port: ${port}`)



require('./models')(connection)

app.listen(port, onListening)

const patients   = require('./controllers/patients'),
      personal    = require('./controllers/personal')


app.use('/api/patients', patients)
app.use('/api/personal', personal)

我得到的错误:Unhandled rejection Error: hospitals is not associated to doctors!

你试过吗?

Doctors.findAll({ include: Hospitals, });

还要去取医生:

Doctors.findAll({ include: [{ model: Hospitals, include: [Medicos], }], });

您必须在两个模型上定义您的关系。另外当你使用 belongsTo 时,你是说医生属于医院,所以 foreignKey 定义在 doctor 上,在这种情况下外键是医院的 id。但是你将 doctor foreignKey 设置为医院的 id,这是行不通的。

module.exports = function(sequelize, DataTypes) {
  var doctors = sequelize.define('doctors', {
    id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    lastName: {
      type: DataTypes.STRING,
      allowNull: false
    },
    SSN: {
      type: DataTypes.STRING,
      allowNull: false
    },
    idData: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      references: { // I'd recommend using the associate functions instead of creating references on the property, only causes confusion from my experience.
        model: 'data',
        key: 'id'
      }
    },
    speciality: {
      type: DataTypes.ENUM('Doctor','Geriatrician'),
      allowNull: false
    },
    // This is the foreignKey property which is referenced in the associate function on BOTH models.
    idHospital: {
      type: DataTypes.INTEGER(11),
      allowNull: false // Using allowNull makes this relationship required, on your model, a doctor can't exist without a hospital.
    },
  }, {
    tableName: 'doctor',
    freezeTableName: true,
    classMethods: {
      associate: models =>  {
        doctors.belongsTo(models.hospitals, {
          foreignKey: "idHospital"
        })
      }
    }
  });

  return doctors;
};

module.exports = function(sequelize, DataTypes) {
  var hospital = sequelize.define('hospitals', {
    id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    idData: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      references: {
        model: 'data',
        key: 'id'
      }
    },
  }, {
    tableName: 'hospitals',
    freezeTableName: true,
    classMethods: {
        associate: models => {
            hospital.hasMany(models.doctors, {
                foreignKey: 'idHospital'
            }
        }
    }
  });

  return hospital;
};

更新

您用来加载模型的文件缺少许多使 sequelize 工作所需的代码。您需要手动调用每个模型的关联函数。 sequelize 提供了一个标准实现,我修改了一点以使用您的代码。

var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");

module.exports = (connection) => {
    var models = {};

    // Here we read in all the model files in your models folder.
    fs
        // This assumes this file is in the same folder as all your
        // models. Then you can simply do require('./modelfoldername')
        // to get all your models.
        .readdirSync(__dirname)
        // We don't want to read this file if it's in the folder. This
        // assumes it's called index.js and removes any files with    
        // that name from the array.
        .filter(function (file) {
            return (file.indexOf(".") !== 0) && (file !== "index.js");
        })
        // Go through each file and import it into sequelize.
        .forEach(function (file) {
            var model = connection.import(path.join(__dirname, file));
            models[model.name] = model;
        });

    // For each model we run the associate function on it so that sequelize
    // knows that they are associated.
    Object.keys(models).forEach(function (modelName) {
        if ("associate" in models[modelName]) {
            models[modelName].associate(models);
        }
    });

    models.connection = connection;
    models.Sequelize = Sequelize;

    return models
}