Как извлекать связанные данные с моделями, сгенерированными в форме Sequalize?

#mysql #node.js #orm #sequelize.js #associations

#mysql #node.js #orm #sequelize.js #ассоциации

Вопрос:

Я разрабатывал серверное приложение NodeJS с поддержкой MySQL с Sequelize в качестве ORM. Я пытаюсь извлечь данные, вызвав созданный мной API. Он отправляет данные в качестве ответа. Но это не затрагивает связанный объект, связанный с отношениями ключей foriegn.

У меня уже была база данных MySQL, и я использовал sequelize ORM, я использовал sequelize-auto для генерации классов моделей. Все классы моделей были сгенерированы успешно. Но ассоциации не были сгенерированы с моделями. Поэтому, чтобы учесть ассоциации, мне пришлось вручную добавить ассоциации в класс модели. Затем я создаю файлы маршрута и создал метод HTTP GET. Но конечная точка API не отправляет данные, как ожидалось.

ниже показаны классы моделей и файлы маршрутов, которые я создал.

 module.exports = function(sequelize, DataTypes) {
    const Department = sequelize.define('Department', {
        department_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false
        },
        description: {
            type: DataTypes.STRING(1000),
            allowNull: true
        }
    }, {
        tableName: 'department',
        timestamps: false,
        underscored: true
    });
    Department.associate = function(models) {
        // associations can be defined here
        Department.hasMany(models.Category, {
            foreignKey: 'department_id',
            as: 'categories',
        });
    };
    return Department;
};
  
 module.exports = function(sequelize, DataTypes) {
    const Category = sequelize.define('Category', {
        category_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        department_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false
        },
        description: {
            type: DataTypes.STRING(1000),
            allowNull: true
        }
    }, {
        tableName: 'category',
        timestamps: false,
        underscored: true
    });
    Category.associate = function(models) {
        // associations can be defined here
        Category.belongsTo(models.Department)
    };
    return Category;
};
  
 var express = require('express');
var router = express.Router();
var model = require('../models/index');

/* GET departments listing. */
router.get('/', function(req, res, next) {
    model.Department.findAll({})
        .then(department => res.json({
            error: false,
            data: department
        }))
        .catch(error => res.json({
            data: [],
            error: true
        }));
});
module.exports = router;
  
 var express = require('express');
var router = express.Router();
var model = require('../models/index');

/* GET category listing. */
router.get('/', function(req, res, next) {
    model.Category.findAll({})
        .then(category => res.json({
            error: false,
            data: category
        }))
        .catch(error => res.json({
            data: [],
            error: true
        }));
});
module.exports = router;
  

Ответ для маршрута / отдела

 {
    "error": false,
    "data": [
        {
            "department_id": 1,
            "name": "Regional",
            "description": "Proud of your country? Wear a T-shirt with a national symbol stamp!"
        },
        {
            "department_id": 2,
            "name": "Nature",
            "description": "Find beautiful T-shirts with animals and flowers in our Nature department!"
        },
        {
            "department_id": 3,
            "name": "Seasonal",
            "description": "Each time of the year has a special flavor. Our seasonal T-shirts express traditional symbols using unique postal stamp pictures."
        }
    ]
}
  

Ответ для маршрута / категории

 {
    "data": [],
    "error": true
}
  

Я ожидал, что данные также будут поступать со связанными объектами. Но он не отправляет данные, как ожидалось. Что я здесь сделал не так.введите описание изображения здесь

Ответ №1:

Дело в том, что вы не указываете в запросе, что вам нужны связанные данные. Для этого вы должны использовать include внутри findAll() функции.

 /* GET departments listing. */
router.get('/', function(req, res, next) {
  model.Department.findAll({
    include: [{
      model: model.Category
      as: 'categories'
    }]
  })
    .then(department => res.json({
      error: false,
      data: department
    }))
    .catch(error => res.json({
      data: [],
      error: true
    }));
});
  

Редактировать:

Я видел, что вы изменили первичный ключ по умолчанию для моделей, поэтому вы также должны указать это в ассоциации категорий. Sequelize по умолчанию работает только с односторонней ассоциацией, в вашем случае от Deparment до Category . Sequelize не знает о Deparment foreignkey в Category , даже когда вы его определили. Вы должны определить, на какой ключ вы указываете.

 Category.associate = function(models) {
  // associations can be defined here
  Category.belongsTo(models.Department,  {as: 'department', foreignKey: 'department_id'})
};
  

Комментарии:

1. спасибо, но когда я добавил параметр include внутри fetchall, это запрос, который он генерирует. запрос недействителен. ВЫБЕРИТЕ Category . category_id , Department . department_id AS Department.department_id , Department . name AS Department.name ИЗ Department description ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ Department.description AS category НА Category . department = Department . Category КАК department_department_id Department . department_id ;

2. Category.department_department_id эта часть неверна, поскольку нет столбца с именем «department_department_id», как это исправить

3. Спасибо, вы спасли мой день!!