Почему sequelize 5 делает это?

#javascript #node.js #express #sequelize.js

#javascript #node.js #выразить #sequelize.js

Вопрос:

Добрый день! Когда я создаю ассоциации между моделями User и Test, sequelize работает нормально. Но когда я хочу добавить новые ассоциации для теста и вопроса, затем sequelize добавляет новый столбец (мой внешний ключ test_id и дополнительный testId ).

Почему?

user.js

 module.exports = (sequelize, DataType) => {
  const User = sequelize.define('user', {
    username: {
      type: DataType.STRING,
      unique: true,
    },
    password: {
      type: DataType.STRING,
    },
  });

  User.associate = (models) => {
    User.hasMany(models.test, {
      foreignKey: 'id',
    });
  };

  return User;
};
 

test.js

 module.exports = (sequelize, DataType) => {
  const Test = sequelize.define('test', {
    title: {
      type: DataType.STRING,
      unique: true,
      required: true,
    },

    description: {
      type: DataType.TEXT,
      required: true,
    },

    picture: { // picture link
      type: DataType.STRING,
    },
  });

  Test.associate = (models) => {
    Test.belongsTo(models.user, {
      foreignKey: 'user_id',
    });
  };

  Test.associate = (models) => {
    Test.hasMany(models.question, {
      foreign_key: 'id',
    });
  };

  return Test;
};
 

question.js

 module.exports = (sequelize, DataType) => {
  const Question = sequelize.define('question', {
    title: {
      type: DataType.STRING,
      required: true,
    },
  });

  Question.associate = (models) => {
    Question.belongsTo(models.test, {
      foreignKey: 'test_id',
    });
  };
  return Question;
};
 

index.js

 const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
require('dotenv').config();

const config = process.env;
const basename = path.basename(module.filename);

const sequelize = new Sequelize({
  database: config.DB_NAME,
  username: config.DB_USER,
  password: config.DB_PASS,
  dialect: config.DB_DIALECT,
});
const db = {};

fs
  .readdirSync(__dirname)
  .filter(file => (file.indexOf('.') !== 0) amp;amp; (file !== basename))
  .forEach((file) => {
    const model = sequelize.import(path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

Object.keys(db).forEach((modelName) => {
  if ('loadScopes' in db[modelName]) {
    db[modelName].loadScopes(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
 

Эти модели генерируют некоторые SQL-запросы:

 Executing (default): CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL auto_increment , `username` VARCHAR(255) UNIQUE, `password` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;

Executing (default): SHOW INDEX FROM `users` FROM `nrforms`

Executing (default): CREATE TABLE IF NOT EXISTS `tests` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255) UNIQUE, `description` TEXT, `picture` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB;

Executing (default): SHOW INDEX FROM `tests` FROM `nrforms`

Executing (default): CREATE TABLE IF NOT EXISTS `questions` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `test_id` INTEGER, `testId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`test_id`) REFERENCES `tests` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`testId`) REFERENCES `tests` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB;

Executing (default): SHOW INDEX FROM `questions` FROM `nrforms`
 

Ответ №1:

Добавьте underscored: false все свои модели:

 module.exports = (sequelize, DataType) => {
    const Question = sequelize.define('question', {
        title: {
            type: DataType.STRING,
            required: true,
        },
    },
        {
            underscored: false, // <---- add this in all your models
        });

    Question.associate = (models) => {
        Question.belongsTo(models.test, {
            foreignKey: 'test_id',
        });
    };
    return Question;
};
 

Ссылка на документацию Sequelize

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

1. Спасибо, но почему ассоциации user и test не создали столбец userId.

2. Это не работает. «СОЗДАТЬ ТАБЛИЦУ, ЕСЛИ ОНА НЕ СУЩЕСТВУЕТ questions ( id ЦЕЛОЕ ЧИСЛО НЕ РАВНО НУЛЮ auto_increment , title VARCHAR(255), createdAt ДАТА-ВРЕМЯ НЕ РАВНО НУЛЮ, updatedAt ДАТА-ВРЕМЯ НЕ РАВНО НУЛЮ, test_id ЦЕЛОЕ ЧИСЛО, testId ЦЕЛОЕ ЧИСЛО, ПЕРВИЧНЫЙ КЛЮЧ ( id ), test_id ССЫЛКИ НА ВНЕШНИЙ КЛЮЧ tests ( id ) ПРИ УДАЛЕНИИ УСТАНАВЛИВАЮТ ЗНАЧЕНИЕ NULL ПРИ КАСКАДНОМ ОБНОВЛЕНИИ, ССЫЛКИ НА ВНЕШНИЙ КЛЮЧ ( testId ) tests id УСТАНАВЛИВАЮТ ЗНАЧЕНИЕ NULL ПРИ УДАЛЕНИИNULL ПРИ ОБНОВЛЕНИИ КАСКАДА) ENGINE=InnoDB; Выполнение (по умолчанию): ПОКАЗАТЬ ИНДЕКС questions ИЗ `nrforms«

3. TestID — был сгенерирован.

4. Это должно было быть решено этим… Мне нужно будет это проверить

Ответ №2:

Я обнаружил проблему.

   Test.associate = (models) => {
    Test.hasMany(models.question, {
      foreignKey: 'id', // was foreign_key: 'id' 
    });
  };
 

Может быть, это ошибка или триггер для автоматического создания обратной ассоциации?
Но я не нашел информации об этом.

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

1. опечатка .. и я подумал, какую конфигурацию вам не хватает 🙂

2. @Shaharyar, ты что-нибудь знаешь об этом свойстве? почему он создает автоматическую обратную ассоциацию?