Rails: Menambahkan indeks setelah menambahkan kolom


119

Misalkan saya membuat tabel tabledi aplikasi Rails. Beberapa waktu kemudian, saya menambahkan kolom yang berjalan:

rails generate migration AddUser_idColumnToTable user_id:string. 

Kemudian saya menyadari bahwa saya perlu menambahkan user_idsebagai indeks. Saya tahu tentang add_indexmetodenya, tetapi di manakah metode ini harus dipanggil? Apakah saya seharusnya menjalankan migrasi (jika ya, yang mana?), Lalu menambahkan dengan tangan metode ini?

Jawaban:


235

Anda dapat menjalankan migrasi lain, hanya untuk indeks:

class AddIndexToTable < ActiveRecord::Migration
  def change
    add_index :table, :user_id
  end
end

4
Jadi saya cukup menjalankan di konsol saya: rel menghasilkan migrasi AddIndexToTable?
pengguna1611830

3
Ya, Anda dapat melakukannya, tetapi Anda harus mengedit migrasi itu setelah itu untuk mencerminkan kode di atas.
Jaap Haagmans

Apakah: tabel seharusnya jamak?
makam

1
@tomb Saya menggunakan contoh dari pertanyaan asli. :tableadalah sebenarnya nama tabel, sehingga dalam kasus usersmeja, Anda akan menggantikan :usersuntuk :table.
Jaap Haagmans

65

Jika Anda perlu membuat, user_idmaka itu akan menjadi asumsi yang masuk akal bahwa Anda mereferensikan tabel pengguna. Dalam hal ini migrasi harus:

rails generate migration AddUserRefToProducts user:references

Perintah ini akan menghasilkan migrasi berikut:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :user, :product, index: true
  end
end

Setelah menjalankan rake db:migratekedua user_idkolom dan indeks akan ditambahkan keproducts meja.

Jika Anda hanya perlu menambahkan indeks ke kolom yang ada, misalnya nameauser meja, teknik berikut ini mungkin membantu:

rails generate migration AddIndexToUsers name:string:index akan menghasilkan migrasi berikut:

class AddIndexToUsers < ActiveRecord::Migration
  def change
    add_column :users, :name, :string
    add_index :users, :name
  end
end

Menghapus add_column baris dan jalankan migrasi.

Dalam kasus yang dijelaskan, Anda bisa mengeluarkan rails generate migration AddIndexIdToTable index_id:integer:indexperintah dan kemudian menghapus add_columnbaris dari migrasi yang dihasilkan. Tetapi saya lebih suka merekomendasikan untuk membatalkan migrasi awal dan menambahkan referensi sebagai gantinya:

rails generate migration RemoveUserIdFromProducts user_id:integer
rails generate migration AddUserRefToProducts user:references

Terima kasih Vadym untuk jawaban lengkapnya. Satu pertanyaan terakhir: mengapa Anda merekomendasikan untuk membatalkan migrasi awal? Apakah nanti ada masalah kinerja terkait dengan penambahan indeks?
Flavio Wuensche

2
Untuk @fwuensche: tidak ada penalti kinerja untuk menambahkan indeks nanti. Logika domain akan menjadi kurang jelas. Misalnya jika Anda memutuskan untuk memutuskan / mengabstraksi / dll asosiasi nanti, Anda harus berurusan dengan dua migrasi terpisah, yang seharusnya menjadi satu ...
Vadym Tyemirov

6
PERINGATAN: Perhatikan bahwa index: true hanya berfungsi dalam migrasi create_table. Migrasi akan berjalan, tetapi tidak ada indeks yang akan dibuat. Lihat makandracards.com/makandra/…
rmcsharry

9

Tambahkan migrasi yang dihasilkan setelah membuat kolom berikut (contoh)

add_index :photographers, :email, :unique => true

maksud Anda sesuatu seperti ini: def self.up add_column ... end add_index ...?
pengguna1611830

5

Untuk referensi Anda bisa menelepon

rails generate migration AddUserIdColumnToTable user:references

Jika di masa mendatang Anda perlu menambahkan indeks umum, Anda dapat meluncurkan ini

rails g migration AddOrdinationNumberToTable ordination_number:integer:index

Hasilkan kode:

class AddOrdinationNumberToTable < ActiveRecord::Migration
  def change
   add_column :tables, :ordination_number, :integer
   add_index :tables, :ordination_number, unique: true
  end
end

0

Anda dapat menggunakan ini, anggap saja Job adalah nama model yang Anda tambahkan index cader_id :

class AddCaderIdToJob < ActiveRecord::Migration[5.2]
  def change
    change_table :jobs do |t|
      t.integer :cader_id
      t.index :cader_id
    end
  end
end
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.