ฉันจะจัดการชื่อดัชนีที่ยาวเกินไปในการโยกย้าย Ruby on Rails ActiveRecord ได้อย่างไร


391

ฉันกำลังพยายามเพิ่มดัชนีเฉพาะที่สร้างขึ้นจากคีย์ต่างประเทศของตารางที่เชื่อมโยงสี่ตาราง:

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"],
  :unique => true

ข้อ จำกัด ของฐานข้อมูลสำหรับชื่อดัชนีทำให้การโยกย้ายล้มเหลว นี่คือข้อความแสดงข้อผิดพลาด:

ชื่อดัชนี 'index_studies_on_user_id_and_university_id_and_subject_name_id_and_subject_type_id' ในตาราง 'การศึกษา' ยาวเกินไป; ขีด จำกัด คือ 64 อักขระ

ฉันจะจัดการสิ่งนี้ได้อย่างไร ฉันสามารถระบุชื่อดัชนีอื่นได้หรือไม่?

คำตอบ:


589

ระบุ:nameตัวเลือกให้add_indexเช่น:

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"], 
  :unique => true,
  :name => 'my_index'

หากใช้:indexตัวเลือกreferencesในcreate_tableบล็อกจะใช้แฮชตัวเลือกเดียวกันกับadd_indexค่าของมัน:

t.references :long_name, index: { name: :my_index }

2
ตาม APIdock ชื่อจะต้องมีสตริงไม่ใช่สัญลักษณ์
Jaco Pretorius

7
ไวยากรณ์สำหรับเรื่องนี้มีremove_index :studies, :name => 'my_index'ไว้สำหรับทุกคนที่ต้องการมัน
Kirk

On Rails ทำงานร่วมกับ4.2.6 index: { name: :my_index }ใช้งานnameไม่ได้เท่านั้น
monteirobrena

174

นอกจากนี้คุณยังสามารถเปลี่ยนชื่อดัชนีในคำจำกัดความคอลัมน์ภายในcreate_tableบล็อก (เช่นคุณได้รับจากเครื่องกำเนิดการโยกย้าย)

create_table :studies do |t|
  t.references :user, index: {:name => "index_my_shorter_name"}
end

5
โปรดทราบว่านี่จะไม่สร้างดัชนีหลายคอลัมน์จากคำถามเดิม มันเป็นเพียงการสาธิตวิธีการย่อชื่อดัชนีแบบยาวจากcreate_table
Craig Walker

6
สิ่งนี้ช่วยฉันเมื่อฉันพยายามสร้างการอ้างอิง polymorphic บนตารางที่เว้นระยะชื่อด้วยดัชนีt.references :searchable, polymorphic:true, index: {:name => "index_searches_on_searchable"}ในกรณีนี้ดัชนีนั้นในความเป็นจริงคอลัมน์หลายคอลัมน์ (searchable_id และ searchable_type) และการเพิ่ม namespace ในชื่อที่สร้างนั้นยาวมาก .
mkrinblk

เป็นทางออกที่ดีกะทัดรัดสำหรับฉัน ขอบคุณ!
Sergio Belevskij

3
ควรจะมีforeign_key: trueและวิธีการนี้เป็นทางออกที่ดีเนื่องจากเป็นวิธีที่ง่ายที่สุดเมื่อคุณมีไฟล์การโยกย้ายที่สร้างขึ้นด้วยmodel:referencesรูปแบบตัวสร้างทางรถไฟ
Abram

39

ใน PostgreSQL, เริ่มต้นจำกัด เป็น 63 ตัวอักษร เนื่องจากชื่อดัชนีต้องไม่ซ้ำกันจึงเป็นเรื่องดีที่จะมีการประชุมเล็กน้อย ฉันใช้ (ฉัน tweaked ตัวอย่างเพื่ออธิบายการก่อสร้างที่ซับซ้อนมากขึ้น):

def change
  add_index :studies, [:professor_id, :user_id], name: :idx_study_professor_user
end

ดัชนีปกติน่าจะเป็น:

:index_studies_on_professor_id_and_user_id

ตรรกะจะเป็น:

  • index กลายเป็น idx
  • ชื่อตารางเอกพจน์
  • ไม่มีคำเข้าร่วม
  • ไม่ _id
  • ลำดับตัวอักษร

ซึ่งมักจะทำหน้าที่


1
ขอบคุณสำหรับการแบ่งปัน. จะดีถ้าคุณสามารถเชื่อมโยงเอกสาร Postgres สำหรับข้อเท็จจริงข้อ จำกัด
JJD

เราต้องการชื่อตารางในชื่อดัชนีเนื่องจากดัชนีอยู่ในตารางนั้นหรือไม่? แค่อยากรู้ว่ามันมีประโยชน์ที่ไหนที่ฉันไม่ได้เห็น
Joshua Pinter

คุณสามารถตั้งชื่อดัชนีสิ่งที่คุณต้องการ แต่ฉันคิดว่าชื่อตารางในชื่อดัชนีช่วยให้ชื่อดัชนีไม่ซ้ำกัน (ซึ่งจำเป็น), ขอบเขตที่ดีและช่วยปรับปรุงการอ่านข้อผิดพลาด
ecoologic


6

คล้ายกับคำตอบก่อนหน้า: เพียงใช้ปุ่ม 'ชื่อ' กับบรรทัดปกติของคุณ add_index:

def change
  add_index :studies, :user_id, name: 'my_index'
end

2

ฉันเกรงว่าโซลูชันเหล่านี้จะไม่ได้ผลสำหรับฉัน อาจเป็นเพราะฉันใช้belongs_toในการโยกย้าย create_table ของฉันสำหรับความสัมพันธ์แบบ polymorphic

ฉันจะเพิ่มรหัสของฉันด้านล่างและลิงก์ไปยังโซลูชันที่ช่วยฉันในกรณีที่คนอื่นสะดุดเมื่อค้นหา 'ชื่อดัชนียาวเกินไป' ที่เกี่ยวข้องกับการเชื่อมโยง polymorphic

รหัสต่อไปนี้ใช้ไม่ได้สำหรับฉัน:

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true
    t.timestamps
  end
  add_index :item_references, [:referenceable_id, :referenceable_type], name: 'idx_item_refs'
end

รหัสนี้ทำงานสำหรับฉัน:

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true, index: { name: 'idx_item_refs' }

    t.timestamps
  end
end

นี่คือคำถามและคำตอบ SO ที่ช่วยฉันได้ที่: https://stackoverflow.com/a/30366460/3258059


1

ฉันมีปัญหานี้ แต่ด้วยtimestampsฟังก์ชั่น มันสร้างดัชนีอัตโนมัติใน updated_at ที่เกินขีด จำกัด อักขระ 63 ตัว:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps
  end
end

ชื่อดัชนี 'index_toooooooooo_loooooooooooooooooooooooooooong_on_updated_at' บนโต๊ะ 'toooooooooo_loooooooooooooooooooooooooooooooooooooooo' ยาวเกินไป; ขีด จำกัด คือ 63 อักขระ

ฉันพยายามใช้timestampsเพื่อระบุชื่อดัชนี:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps index: { name: 'too_loooooooooooooooooooooooooooooong_updated_at' }
  end
end

อย่างไรก็ตามสิ่งนี้พยายามใช้ชื่อดัชนีกับทั้งสองupdated_atและcreated_atฟิลด์:

ชื่อดัชนี 'too_long_updated_at' บนโต๊ะ 'toooooooooo_loooooooooooooooooooooooooooooooooooooooooooooooooo' แล้ว

ในที่สุดฉันก็ยอมแพ้timestampsและเพิ่งสร้างการประทับเวลาในระยะยาว:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.datetime :updated_at, index: { name: 'too_long_on_updated_at' }
    t.datetime :created_at, index: { name: 'too_long_on_created_at' }
  end
end

ใช้งานได้ แต่ฉันชอบที่จะได้ยินว่าเป็นไปได้ด้วยtimestampsวิธีการ!



0

ฉันมีโครงการที่ใช้เครื่องกำเนิดไฟฟ้าจำนวนมากและต้องการให้มันเป็นแบบอัตโนมัติดังนั้นฉันจึงคัดลอกindex_nameฟังก์ชั่นจากแหล่งที่มาของรางเพื่อลบล้างมัน ฉันเพิ่มสิ่งนี้ในconfig/initializers/generated_index_name.rb:

# make indexes shorter for postgres
require "active_record/connection_adapters/abstract/schema_statements"
module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module SchemaStatements
      def index_name(table_name, options) #:nodoc:
        if Hash === options
          if options[:column]
            "ix_#{table_name}_on_#{Array(options[:column]) * '__'}".slice(0,63)
          elsif options[:name]
            options[:name]
          else
            raise ArgumentError, "You must specify the index name"
          end
        else
          index_name(table_name, index_name_options(options))
        end
      end
    end
  end
end

มันสร้างดัชนีเช่นix_assignments_on_case_id__project_idและเพียงตัดให้เหลือ 63 ตัวอักษรหากยังยาวเกินไป นั่นจะยังคงไม่ซ้ำกันหากชื่อตารางยาวมาก แต่คุณสามารถเพิ่มความยุ่งยากได้เช่นทำให้ชื่อตารางสั้นลงแยกจากชื่อคอลัมน์หรือตรวจสอบความเป็นเอกลักษณ์จริง ๆ

หมายเหตุนี่มาจากโครงการ Rails 5.2 หากคุณตัดสินใจที่จะทำสิ่งนี้ให้คัดลอกแหล่งที่มาจากเวอร์ชั่นของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.