मैं रूबी 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विकल्प का उपयोग किया जाता है, तो वह उसी मान के समान विकल्प हैश लेता है :referencescreate_tableadd_index

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

2
एपीआईडॉक के अनुसार नाम को एक स्ट्रिंग होना चाहिए, प्रतीक नहीं
जैको प्रीटोरियस

7
इसके लिए डाउन सिंटैक्स remove_index :studies, :name => 'my_index'किसी ऐसे व्यक्ति के लिए है जिसे इसकी आवश्यकता है
किर्क

रेल के 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
क्रेग वाकर

6
इससे मुझे तब मदद मिली जब मैं एक सूचकांक के साथ एक नाम स्थान तालिका पर एक बहुरूपी संदर्भ बनाने की कोशिश कर रहा था t.references :searchable, polymorphic:true, index: {:name => "index_searches_on_searchable"}, इस मामले में सूचकांक वास्तव में एक बहु-स्तंभ (खोजा जा रहा था और खोजा जा रहा था) और उत्पन्न नाम के नाम के अलावा बहुत लंबा हो गया ।
22

मेरे लिए अच्छा, कॉम्पैक्ट समाधान। धन्यवाद!
सर्जियो बेलेवस्कीज

3
भी होना चाहिए foreign_key: trueऔर वैसे, यह एक शानदार समाधान है क्योंकि इसका उपयोग करना सबसे आसान है जब आपके पास रेल जनरेटर model:referencesप्रारूप के साथ बनाई गई एक माइग्रेशन फ़ाइल है
अब्राम

39

PostgreSQL में, डिफ़ॉल्ट सीमा 63 वर्ण है । क्योंकि अनुक्रमणिका नाम अद्वितीय होना चाहिए, यह थोड़ा सा सम्मेलन होना अच्छा है। मैं उपयोग करता हूं (मैंने अधिक जटिल निर्माणों को समझाने के लिए उदाहरण दिया):

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
साझा करने के लिए धन्यवाद। अच्छा होगा यदि आप सीमा के तथ्य के लिए पोस्टग्रेज प्रलेखन को लिंक कर सकते हैं।
JJD

क्या हमें इंडेक्स नाम में टेबल का नाम चाहिए क्योंकि इंडेक्स वैसे भी टेबल से संबंधित है? बस उत्सुक अगर वह कहीं फायदेमंद है जो मैंने नहीं देखा है।
जोशुआ पिन्टर

आप इंडेक्स को नाम दे सकते हैं जो आप चाहते हैं, लेकिन मुझे लगता है कि इंडेक्स नाम में टेबल का नाम इंडेक्स नाम को अद्वितीय रखने में मदद करता है (जो अनिवार्य है), अच्छी तरह से स्कूप किया गया और कुछ त्रुटि संदेश पठनीयता में सुधार करता है।
पारिस्थितिक जूल


6

पिछले उत्तर के समान: बस अपने नियमित add_index लाइन के साथ 'नाम' कुंजी का उपयोग करें:

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

2

मुझे डर है कि इनमें से कोई भी समाधान मेरे लिए काम नहीं करता। शायद इसलिए कि मैं उपयोग कर रहा थाbelongs_to एक पॉलीमॉर्फिक एसोसिएशन के लिए मेरे create_table माइग्रेशन में ।

मैं अपने कोड को नीचे जोड़ूंगा और समाधान के लिए एक लिंक दूंगा, जो पॉलीमॉर्फिक एसोसिएशनों के संबंध में 'इंडेक्स नाम बहुत लंबा है' की खोज करने पर किसी और को ठोकर खाने में मेरी मदद करता है।

निम्नलिखित कोड मेरे लिए काम नहीं किया:

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 Q & A है जिसने मेरी मदद की: https://stackoverflow.com/a/30366460/3258059


1

मेरे पास यह मुद्दा था, लेकिन timestampsफ़ंक्शन के साथ । यह अद्यतित_एट पर एक सूचकांक को स्वत: उत्पन्न कर रहा था जो 63 वर्ण सीमा से अधिक था:

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

अनुक्रमणिका नाम 'index_toooooooo_loooooooooooooooooooooooooooooong_on_updated_at' टेबल पर 'toooooooooo_loooooooooooooooooooooooooooong' बहुत लंबा है; सीमा 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_loooooooooooooooooooooooooooooong' पहले से मौजूद है

अंत में मैंने 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 अक्षरों में बदल देता है। यदि तालिका का नाम बहुत लंबा है, तो यह अभी भी गैर-अद्वितीय होने जा रहा है, लेकिन आप स्तंभ नाम से अलग तालिका नाम को छोटा करने या वास्तव में विशिष्टता की जाँच करने जैसी जटिलताओं को जोड़ सकते हैं।

ध्यान दें, यह एक रेल 5.2 परियोजना से है; यदि आप ऐसा करने का निर्णय लेते हैं, तो अपने संस्करण से स्रोत की प्रतिलिपि बनाएँ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.