2016-06-18 23 views
3

如果您要啓用Sequelize日誌記錄,您會看到在「同步」階段和創建表格之後,Sequelize執行SHOW INDEX FROM table查詢。問題是 - 爲什麼?爲什麼會將問題「從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` 

回答

4

爲什麼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如何在這裏工作?

通過發佈SHOW INDEX FROM並將返回值與模型的索引進行比較,Sequelize確定哪些索引是新的。如果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 
 
)); 
 
})

+0

非常感謝您的細化分解!現在我們有一個完全清晰的畫面。 – alecxe

+0

不客氣!我很高興能夠提供幫助。 –

+1

它是否刪除ORM中未定義的索引? – elmigranto