javascript - 为什么 Sequelize 发布 "SHOW INDEX FROM ` 表`"?

标签 javascript sql node.js orm sequelize.js

如果启用 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`

最佳答案

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
  ));
})

关于javascript - 为什么 Sequelize 发布 "SHOW INDEX FROM ` 表`"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37893128/

相关文章:

javascript - 关于如何在 javascript/HTML5/NodeJS 中实现客户端-服务器-客户端基础设施的想法

PHP/MYSQL 需要 SQL Join 吗?

javascript - 禁用仅在生产环境 sails js 中运行的 Grunt 任务?

angularjs - Protractor 中有 before() 函数吗?

javascript - 无法从远程 iframe 调用父函数

javascript - React redux reducer 从状态获取数据?

php - Mysql 函数 count() 逐行计数

sql - 编写 T-SQL 时使用 WHERE + AND + CASE + IN

javascript - Angular2/Electron 应用程序在 Angular2 ts 文件中使用 Electron API

javascript - 在浏览器上呈现转义的 XML