如果您启用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`
续集使用SHOW INDEX FROM
的原因是避免第二次将现有索引添加到模型的表中。第二次添加现有索引将导致错误。
续集当前不够"聪明",无法理解您尚未定义任何索引。无论如何,它都会检查表。
在您的情况下,由于您强制同步而不会有所作为。这意味着这些表总是被删除和新创建。添加新索引时,不会有任何现有索引。
想象您将指定具有这样的索引的模型:
sequelize.define('user', {}, {
indexes: [
// Create a unique index on email
{
unique: true,
fields: ['email']
}
]
})
该示例的广泛形式可以在http://docs.sequs.sequeslizejs.com/en/latest/docs/models-definition/#indexes中找到。
虚构故事
如果您昨天使用quelize.sync()创建了表没有现有索引),续集将仅添加新索引。
在此处如何续集工作?
续集通过发出SHOW INDEX FROM
并将返回值与模型的索引进行比较,确定了哪些索引是新的。如果续集发现模型中的索引比现有表中有更多(或不同的)索引,则将这些索引添加到基础表中。
可以在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
));
})