खोज…


परिचय

ActiveRecord MVC में M है जो व्यापार डेटा और तर्क का प्रतिनिधित्व करने के लिए जिम्मेदार प्रणाली की परत है। तकनीक एक संबंधपरक डेटाबेस प्रबंधन प्रणाली में तालिकाओं के लिए एक आवेदन पत्र की समृद्ध वस्तुओं जोड़ता है हे bject आर elational एम apper (ORM) है।

ActiveRecord आपके लिए डेटाबेस पर क्वेरी करेगा और अधिकांश डेटाबेस सिस्टम के साथ संगत है। भले ही आप डेटाबेस प्रणाली का उपयोग कर रहे हों, ActiveRecord विधि प्रारूप हमेशा समान रहेगा।

।कहाँ पे

where विधि किसी भी ActiveRecord मॉडल पर उपलब्ध है और दिए गए मानदंड से मेल खाने वाले रिकॉर्ड के सेट के लिए डेटाबेस को क्वेरी करने की अनुमति देता है।

where विधि एक हैश स्वीकार करता है जहाँ कुंजियाँ उस तालिका नाम के स्तंभ नामों से मेल खाती हैं जो मॉडल प्रस्तुत करता है।

एक सरल उदाहरण के रूप में, हम निम्नलिखित मॉडल का उपयोग करेंगे:

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
end

Sven के पहले नाम के साथ सभी लोगों को खोजने के लिए:

people = Person.where(first_name: 'Sven')
people.to_sql # "SELECT * FROM people WHERE first_name='Sven'"

Sven के पहले नाम और Schrodinger अंतिम नाम वाले सभी लोगों को खोजने के लिए:

people = Person.where(first_name: 'Sven', last_name: 'Schrodinger')
people.to_sql # "SELECT * FROM people WHERE first_name='Sven' AND last_name='Schrodinger'"

उपर्युक्त उदाहरण में, sql आउटपुट दिखाता है कि रिकॉर्ड केवल तभी लौटाया जाएगा जब first_name और last_name दोनों मेल खाते हों।

OR शर्त के साथ क्वेरी

first_name == 'Bruce' या last_name == 'Wayne' साथ रिकॉर्ड खोजने के लिए

User.where('first_name = ? or last_name = ?', 'Bruce', 'Wayne')
# SELECT "users".* FROM "users" WHERE (first_name = 'Bruce' or last_name = 'Wayne')

एक सरणी के साथ

where किसी भी ActiveRecord मॉडल पर विधि का उपयोग फॉर्म के SQL को उत्पन्न करने के लिए किया जा सकता है WHERE column_name IN (a, b, c, ...) । यह एक सरणी को तर्क के रूप में पारित करके प्राप्त किया जाता है।

एक सरल उदाहरण के रूप में, हम निम्नलिखित मॉडल का उपयोग करेंगे:

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
end

people = Person.where(first_name: ['Mark', 'Mary'])
people.to_sql # "SELECT * FROM people WHERE first_name IN ('Mark', 'Mary')"

सरणी एक हैं, तो nil , एसक्यूएल जांच करने के लिए संशोधित किया जाएगा यदि स्तंभ है null :

people = Person.where(first_name: ['Mark', 'Mary', nil])
people.to_sql # "SELECT * FROM people WHERE first_name IN ('Mark', 'Mary') OR first_name IS NULL"

कार्यक्षेत्र

स्कोप्स ActiveRecord मॉडल पर पूर्वनिर्धारित फ़िल्टर के रूप में कार्य करते हैं।

scope क्लास पद्धति का उपयोग करके एक स्कोप परिभाषित किया गया है।

एक सरल उदाहरण के रूप में, हम निम्नलिखित मॉडल का उपयोग करेंगे:

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
  #attribute :age, :integer

  # define a scope to get all people under 17
  scope :minors, -> { where(age: 0..17) }

  # define a scope to search a person by last name
  scope :with_last_name, ->(name) { where(last_name: name) }

end

स्कोप को सीधे मॉडल क्लास से दूर बुलाया जा सकता है:

minors = Person.minors

स्कोप्स जंजीर हो सकते हैं:

peters_children = Person.minors.with_last_name('Peters')

where विधि और अन्य क्वेरी प्रकार विधियों को भी जंजीर किया जा सकता है:

mary_smith = Person.with_last_name('Smith').where(first_name: 'Mary')

पर्दे के पीछे, एक मानक वर्ग विधि के लिए स्कोप बस सिंटैक्टिक चीनी हैं। उदाहरण के लिए, ये विधियां कार्यात्मक रूप से समान हैं:

scope :with_last_name, ->(name) { where(name: name) }

# This ^ is the same as this:

def self.with_last_name(name)
  where(name: name)
end

डिफ़ॉल्ट स्कोप

मॉडल में सभी कार्यों के लिए एक डिफ़ॉल्ट गुंजाइश सेट करने के लिए अपने मॉडल में।

scope मेथड और एक क्लास मेथड के बीच एक उल्लेखनीय अंतर है: scope डिफाइन्ड स्कोप्स हमेशा एक ActiveRecord::Relation लौटाएंगे, भले ही रिटर्न के भीतर तर्क शून्य हो। वर्ग विधियाँ, हालांकि, ऐसा कोई सुरक्षा जाल नहीं है और यदि वे कुछ और लौटाते हैं तो श्रृंखलाबद्धता को तोड़ सकते हैं।

where.not

where खंडों का उपयोग करके खंड को where.not जा सकता है।

class Person < ApplicationRecord
  #attribute :first_name, :string
end

people = Person.where.not(first_name: ['Mark', 'Mary'])
# => SELECT "people".* FROM "people" WHERE "people"."first_name" NOT IN ('Mark', 'Mary')

ActiveRecord द्वारा समर्थित 4.0 और बाद में।

आदेश

आप का उपयोग करके ActiveRecord क्वेरी परिणामों आदेश कर सकते हैं .order :

User.order(:created_at)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15 10:21:48">]

यदि निर्दिष्ट नहीं है, तो आरोही क्रम में आदेश दिया जाएगा। आप इसे करके निर्दिष्ट कर सकते हैं:

User.order(created_at: :asc)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15 10:21:48">]

User.order(created_at: :desc)
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13 16:51:18">]

.order भी एक स्ट्रिंग को स्वीकार करता है, इसलिए आप भी कर सकते हैं

User.order("created_at DESC")
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13 16:51:18">]

जैसा कि स्ट्रिंग कच्चा एसक्यूएल है, आप एक तालिका भी निर्दिष्ट कर सकते हैं और न केवल एक विशेषता। यह मानते हुए कि आप users को उनकी role नाम के अनुसार क्रम देना चाहते हैं, आप ऐसा कर सकते हैं:

Class User < ActiveRecord::Base
    belongs_to :role
end

Class Role < ActiveRecord::Base
  has_many :users
end

User.includes(:role).order("roles.name ASC")

order गुंजाइश भी एक नोड नोड स्वीकार कर सकते हैं:

User.includes(:role).order(User.arel_table[:name].asc)

ActiveRecord बैंग (!) विधियाँ

यदि आपको विफलता के मामले में false मूल्य के बजाय अपवाद जुटाने के लिए ActiveRecord विधि की आवश्यकता है, तो आप जोड़ सकते हैं ! उनको। यह बहुत महत्वपूर्ण है। यदि आप उपयोग नहीं करते हैं तो कुछ अपवादों / असफलताओं को पकड़ना मुश्किल है! उन पर। मैंने आपको अपने विकास चक्र में ऐसा करने की सलाह दी है ताकि आप अपना समय बचाने के लिए अपने सभी ActiveRecord कोड को इस तरह से लिख सकें।

Class User < ActiveRecord::Base
  validates :last_name, presence: true
end

User.create!(first_name: "John")
#=> ActiveRecord::RecordInvalid: Validation failed: Last name can't be blank

ActiveRecord विधियाँ जो एक धमाके को स्वीकार करती हैं ( ! ) हैं:

  • .create!
  • .take!
  • .first!
  • .last!
  • .find_by!
  • .find_or_create_by!
  • #save!
  • #update!
  • सभी एआर गतिशील खोजक

.find_by

आप find_by का उपयोग करके अपनी तालिका के किसी भी क्षेत्र के रिकॉर्ड पा सकते हैं।

इसलिए, यदि आपके पास एक User मॉडल है जिसमें first_name विशेषता है जो आप कर सकते हैं:

User.find_by(first_name: "John")
#=> #<User id: 2005, first_name: "John", last_name: "Smith">

ऐसा find_by है कि find_by डिफ़ॉल्ट रूप से कोई अपवाद नहीं फेंकता है। यदि परिणाम एक खाली सेट है, तो यह find बजाय nil लौटाता है।

यदि अपवाद की आवश्यकता है तो find_by! उपयोग कर सकते हैं find_by! कि एक को जन्म देती है ActiveRecord::RecordNotFound तरह त्रुटि find

।सभी हटा दो

यदि आपको बहुत सारे रिकॉर्ड जल्दी से हटाने की आवश्यकता है, तो ActiveRecord .delete_all विधि देता है। उस तालिका, या एक संग्रह के सभी रिकॉर्ड को हटाने के लिए, सीधे एक मॉडल पर बुलाया जाएगा। हालांकि सावधान रहें, क्योंकि .delete_all किसी भी वस्तु को .delete_all नहीं देता है इसलिए कोई कॉलबैक नहीं देता है ( before_* और after_destroy ट्रिगर नहीं होता है)।

User.delete_all
#=> 39  <-- .delete_all return the number of rows deleted

User.where(name: "John").delete_all 

ActiveRecord केस असंवेदनशील खोज

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

आप ActiveRecord की अंतर्निहित Arel matches विधि का उपयोग सुरक्षित तरीके से करने के लिए कर सकते हैं:

addresses = Address.arel_table
Address.where(addresses[:address].matches("%street%"))

Arel डेटाबेस इंजन को कॉन्फ़िगर करने के लिए उपयुक्त LIKE या ILIKE कंस्ट्रक्शन लागू करेगा।

पहला और अंतिम रिकॉर्ड प्राप्त करें

डेटाबेस से first और last रिकॉर्ड प्राप्त करने के लिए रेल के पास बहुत आसान तरीका है।

users तालिका से first रिकॉर्ड प्राप्त करने के लिए हमें निम्नलिखित कमांड टाइप करने की आवश्यकता है:

User.first

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा:

SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` ASC LIMIT 1

और रिकॉर्ड के बाद वापस आ जाएगा:

#<User:0x007f8a6db09920 id: 1, first_name: foo, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00, updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >

users तालिका से last रिकॉर्ड प्राप्त करने के लिए हमें निम्नलिखित कमांड टाइप करने की आवश्यकता है:

User.last

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा:

SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` DESC LIMIT 1

और रिकॉर्ड के बाद वापस आ जाएगा:

#<User:0x007f8a6db09920 id: 10, first_name: bar, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00, updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >

पहली और आखिरी विधि करने के लिए एक पूर्णांक पासिंग वस्तुओं की एक सीमा क्वेरी और रिटर्न सरणी पैदा करता है।

User.first(5)

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा।

SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 5

तथा

User.last(5)

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा।

SELECT  "users".* FROM "users"  ORDER BY "users"."id" DESC LIMIT 5

.group और .count

हमारे पास एक Product मॉडल है और हम उन्हें उनकी category अनुसार समूह बनाना चाहते हैं।

Product.select(:category).group(:category)

यह डेटाबेस को निम्नानुसार क्वेरी करेगा:

SELECT "product"."category" FROM "product" GROUP BY "product"."category"

सुनिश्चित करें कि समूहीकृत फ़ील्ड भी चयनित है। समूहन - विशेष रूप से घटना की गणना के लिए - इस मामले में - categories लिए उपयोगी है।

Product.select(:category).group(:category).count

जैसा कि क्वेरी से पता चलता है, यह गिनती के लिए डेटाबेस का उपयोग करेगा, जो पहले रिकॉर्ड को प्राप्त करने और कोड में गिनती करने की तुलना में बहुत अधिक कुशल है:

SELECT COUNT("products"."category") AS count_categories, "products"."category" AS products_category FROM "products" GROUP BY "products"."category"

डीडीस्टिंक्ट (या। क्यूनीक)

यदि आप किसी परिणाम से डुप्लिकेट हटाना चाहते हैं, तो आप .distinct() उपयोग कर सकते हैं:

Customers.select(:country).distinct

यह डेटाबेस पर निम्नानुसार प्रश्न करता है:

SELECT DISTINCT "customers"."country" FROM "customers"

.uniq() का समान प्रभाव है। रेल 5.0 के साथ यह पदावनत हो गया और इसे 5.1 संस्करण के साथ रेल से हटा दिया जाएगा। इसका कारण यह है, unique शब्द का अलग अर्थ नहीं है और यह भ्रामक हो सकता है। इसके अलावा distinct SQL सिंटैक्स के करीब है।

में शामिल

joins() आपको अपने वर्तमान मॉडल में तालिकाओं में शामिल होने की अनुमति देता है। पूर्व के लिए।

User.joins(:posts)

निम्न SQL क्वेरी का उत्पादन करेगा:

"SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id""

तालिका में शामिल होने के बाद, आपको इसकी पहुँच प्राप्त होगी:

User.joins(:posts).where(posts: { title: "Hello world" })

बहुवचन रूप पर ध्यान दें। यदि आपका संबंध है :has_many , तो :has_many joins() तर्क बहुवचन होना चाहिए। अन्यथा, एकवचन का उपयोग करें।

नेस्टेड joins :

User.joins(posts: :images).where(images: { caption: 'First post' })

जो उत्पादन करेगा:

"SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" INNER JOIN "images" ON "images"."post_id" = "images"."id""

शामिल

ActiveRecord के साथ यह सुनिश्चित करना includes कि सभी निर्दिष्ट संघों को कम से कम प्रश्नों की संभावित संख्या का उपयोग करके लोड किया जाए। इसलिए जब किसी संबंधित तालिका के साथ डेटा के लिए एक तालिका को क्वेरी करते हैं, तो दोनों तालिकाओं को मेमोरी में लोड किया जाता है।

@authors = Author.includes(:books).where(books: { bestseller: true } )

# this will print  results without additional db hitting
@authors.each do |author| 
  author.books.each do |book|
    puts book.title
  end
end

Author.joins(:books).where(books: { bestseller: true } ) केवल लेखकों को लोडिंग पुस्तकों के बिना स्मृति में शर्तों के साथ लोड करेगी। नेस्टेड एसोसिएशन के बारे में अतिरिक्त जानकारी की आवश्यकता नहीं होने पर joins उपयोग करें।

@authors = Author.joins(:books).where(books: { bestseller: true } )

# this will print results without additional queries
@authors.each { |author| puts author.name }

# this will print results with additional db queries
@authors.each do |author| 
  author.books.each do |book|
    puts book.title
  end
end

सीमा और ऑफसेट

आप रिकॉर्ड किए जाने वाले रिकॉर्ड की संख्या बताने के लिए limit का उपयोग कर सकते हैं, और रिकॉर्ड वापस करने के लिए शुरू करने से पहले छोड़ने के लिए रिकॉर्ड की संख्या बताने के लिए offset का उपयोग कर सकते हैं।

उदाहरण के लिए

User.limit(3) #returns first three records

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा।

"SELECT  `users`.* FROM `users` LIMIT 3"

जैसा कि उपरोक्त क्वेरी में ऑफसेट का उल्लेख नहीं किया गया है, इसलिए यह पहले तीन रिकॉर्ड लौटाएगा।

User.limit(5).offset(30) #returns 5 records starting from 31th i.e from 31 to 35

यह निम्नलिखित sql क्वेरी उत्पन्न करेगा।

"SELECT  `users`.* FROM `users` LIMIT 5 OFFSET 30"


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow