Зачем секвенировать вопросы "показать индекс из таблицы"?


Если бы вы включили ведение журнала Sequelize, вы бы увидели, что во время фазы "синхронизация" и сразу после создания таблицы Sequelize выполняет запрос SHOW INDEX FROM table. Вопрос в том-почему?


Чтобы быть более конкретным, вот код, который я выполняю:

var Sequelize = require('sequelize');

var connection = new Sequelize('demo_schema', 'root', 'password');

var Article = connection.define('article', {
    slug: {
        type: Sequelize.STRING,
        primaryKey: true
    },
    title: {
        type: Sequelize.STRING,
        unique: true,
        allowNull: false
    },
    body:  {
        type: Sequelize.TEXT
    }
}, {
    timestamps: false
});

connection.sync({
    force: true,
    logging: console.log
}).then(function () {
   // TODO
});

Вот вывод на консоль:

Executing (default): DROP TABLE IF EXISTS `articles`;
Executing (default): DROP TABLE IF EXISTS `articles`;
Executing (default): CREATE TABLE IF NOT EXISTS `articles` (`slug` VARCHAR(255) , `title` VARCHAR(255) NOT NULL UNIQUE, `body` TEXT, UNIQUE `articles_title_unique` (`title`), PRIMARY KEY (`slug`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `articles`
1 3

1 ответ:

Причина, по которой Sequelize использует SHOW INDEX FROM, заключается в том, чтобы избежать повторного добавления существующих индексов в таблицу модели. Добавление существующего индекса во второй раз приведет к ошибке.

Sequelize в настоящее время недостаточно" умна", чтобы понять, что вы не определили никаких индексов. Он все равно проверяет таблицу.

В вашем сценарии это не имеет значения, так как вы принудительно синхронизируете. Это означает, что таблицы всегда удаляются и создаются заново. При добавлении новых индексов их не будет существующий индекс.

Представьте, что вы задали бы модель с индексами так:

sequelize.define('user', {}, {
  indexes: [
    // Create a unique index on email
    {
      unique: true,
      fields: ['email']
    }
  ]
})
Развернутую форму этого примера можно найти в http://docs.sequelizejs.com/en/latest/docs/models-definition/#indexes .

Вымышленная История

Если вы создали таблицу с Sequelize.sync () вчера добавил новый индекс в вашу модель сегодня и не будет использовать принудительную синхронизацию (потому что тогда таблица будет удалена и создана -- > нет существующие индексы), Sequelize добавит только новый индекс.

Как здесь работает Sequelize?

Sequelize определяет, какие индексы являются новыми, выдавая SHOW INDEX FROM и сравнивая возвращаемое значение с индексами вашей модели. Если Sequelize обнаружит, что в вашей модели больше (или больше) индексов, чем в существующей таблице, он добавит эти индексы в базовую таблицу.

Код, делающий это, можно найти наGitHub . В следующем фрагменте кода я добавлены некоторые комментарии к соответствующему коду:

// this.QueryInterface.showIndex produces the statement `SHOW INDEX FROM [table of the model]`. It returns a promise containing the found indexes.
.then(() => this.QueryInterface.showIndex(this.getTableName(options), options))
// `indexes` will contain the indexes which are present on the existing table.
// If you force sync, this will always be empty since the table is new.
.then(indexes => {
  // Assign an auto-generated name to indexes which are not named by the user
  this.options.indexes = this.QueryInterface.nameIndexes(this.options.indexes, this.tableName);

  // Fill `indexes` with only the indexes from your model which are not present on the table.
  indexes = _.filter(this.options.indexes, item1 => !_.some(indexes, item2 => item1.name === item2.name));

  // .map iterates over `indexes` and adds an index for each entry.
  // Remeber, this is for indexes which are present in the model definition but not present on the table.
  return Promise.map(indexes, index => this.QueryInterface.addIndex(
    this.getTableName(options),
    _.assign({
      logging: options.logging,
      benchmark: options.benchmark,
      transaction: options.transaction
    }, index),
    this.tableName
  ));
})