ActiveRecord या क्वेरी


180

आप RAIL 3 ActiveRecord में OR क्वेरी कैसे करते हैं। मेरे द्वारा खोजे गए सभी उदाहरणों में केवल और प्रश्न हैं।

संपादित करें: या विधि रेल 5 से उपलब्ध है। ActiveRecord :: QueryMethods देखें


7
SQL सीखें। ActiveRecord चीजों को काम करना आसान बनाता है, लेकिन आपको अभी भी जानना होगा कि आपके प्रश्न क्या कर रहे हैं, अन्यथा आपका प्रोजेक्ट स्केल नहीं कर सकता है। मैंने यह भी सोचा कि मैं एसक्यूएल से निपटने के बिना कभी भी मिल सकता हूं, और मैं इसके बारे में बहुत गलत था।
ryan0

1
@ ryan0, आप बहुत सही हैं। हम फैंसी रत्नों और अन्य चीजों का उपयोग कर सकते हैं, लेकिन हमें इस बात की जानकारी होनी चाहिए कि ये रत्न अंदर क्या कर रहे हैं और अंतर्निहित तकनीक क्या है, और हो सकता है कि मणि की मदद के बिना अंतर्निहित तकनीकों का उपयोग करें, यदि आवश्यकता हो, तो प्रदर्शन। रत्नों को एक विशेष संख्या में यूजेस को ध्यान में रखते हुए बनाया जाता है, लेकिन ऐसी परिस्थितियां हो सकती हैं, जहां हमारी परियोजना में एक वीक्षक अलग हो सकता है।
रुबिप्रंस


1
चूंकि रेल्स 5, IMHO का स्वीकृत उत्तर ग्रेग ऑलसेन संस्करण होना चाहिए:Post.where(column: 'something').or(Post.where(other: 'else'))
फिलिप क्लेन

6
इस सवाल में रूबी-ऑन-रेल्स -3 का टैग है। स्वीकृत उत्तर केवल रेल 5 से संबंधित क्यों होगा?
ulty फैकल्टी

जवाबों:


109

ARel का प्रयोग करें

t = Post.arel_table

results = Post.where(
  t[:author].eq("Someone").
  or(t[:title].matches("%something%"))
)

परिणामी SQL:

ree-1.8.7-2010.02 > puts Post.where(t[:author].eq("Someone").or(t[:title].matches("%something%"))).to_sql
SELECT     "posts".* FROM       "posts"  WHERE     (("posts"."author" = 'Someone' OR "posts"."title" LIKE '%something%'))

थोड़ा गड़बड़ लगता है, लेकिन कम से कम मैं sql नहीं लिख रहा हूं, जो सिर्फ गलत लगता है! मैं और अधिक का उपयोग करने पर ध्यान देने जा रहा हूं।
pho3nixf1re

54
मैं विश्वास नहीं कर सकता कि सीक्वल कितना अधिक सुरुचिपूर्ण है
मैकारो

3
SQL में कुछ भी गलत नहीं है। जो चीज गलत हो सकती है वह यह है कि हम SQL स्ट्रिंग अर्थात् SQL इंजेक्शन का निर्माण कैसे करते हैं । इसलिए, हमें उस SQL ​​इनपुट को प्रदान करने से पहले उपयोगकर्ता इनपुट को sanitize करना होगा जो डेटाबेस के विरुद्ध चलाया जाना है। यह ओआरएम के द्वारा संभाला जाएगा , और ये किनारे के मामलों को संभाल रहे हैं, जिन्हें हम याद करते हैं। इसलिए, SQL क्वेरी बनाने के लिए ORM का उपयोग करना हमेशा उचित होता है ।
रबीप्रिंस

5
SQL के साथ एक और समस्या यह है कि यह डेटाबेस अज्ञेयवादी नहीं है। उदाहरण के लिए sqlite (डिफ़ॉल्ट रूप से असंवेदनशील मामला) और पोस्टग्रेज पर (ऑपरेटर की तरह स्पष्ट मामले असंवेदनशील की जरूरत है ) के लिए matchesउत्पादन करेगा । LIKEILIKE
21

1
@ToniLeigh ActiveRecord हुड के तहत SQL का उपयोग कर रहा है। यह एसक्यूएल प्रश्नों को लिखने के लिए सिर्फ एक वाक्यविन्यास है जो एसक्यूएल सैनिटाइजेशन को संभालता है और आपके प्रश्नों को डीबी अज्ञेयवादी बनाता है। एकमात्र ओवरहेड है जहाँ रेल वाक्य को SQL क्वेरी में रूपांतरित करता है। और यह केवल मिलीसेकंड की बात है। बेशक आपको सबसे अच्छा प्रदर्शन करने वाला SQL क्वेरी लिखना चाहिए और इसे ActiveRecord सिंटैक्स में बदलने का प्रयास करना चाहिए। यदि ActiveRecord सिंटैक्स में SQL का प्रतिनिधित्व नहीं किया जा सकता है, तो आपको सादे SQL के लिए जाना चाहिए।
रुबिप्रिंस

208

यदि आप किसी स्तंभ के मान पर OR ऑपरेटर का उपयोग करना चाहते हैं, तो आप किसी सरणी को पास कर सकते हैं .whereऔर ActiveRecord उपयोग करेंगे IN(value,other_value):

Model.where(:column => ["value", "other_value"]

आउटपुट:

SELECT `table_name`.* FROM `table_name` WHERE `table_name`.`column` IN ('value', 'other_value')

यह ORएक एकल स्तंभ पर एक के बराबर प्राप्त करना चाहिए


13
यह सबसे साफ "रेल रास्ता" उत्तर है, स्वीकार किया जाना चाहिए था
8:09

10
धन्यवाद @koonse, यह बिल्कुल 'OR' क्वेरी नहीं है, लेकिन यह इस स्थिति के लिए एक ही परिणाम पैदा करता है।
डेडकर्मा

मदद अगर आप कर सकते हैं - stackoverflow.com/questions/15517286/…
प्रतीक बोथरा

79
यह समाधान OR का प्रतिस्थापन नहीं है, क्योंकि आप इस तरह से दो अलग-अलग कॉलम का उपयोग नहीं कर सकते हैं।
फॉटेनस

151

रेल 3 में, यह होना चाहिए

Model.where("column = ? or other_column = ?", value, other_value)

इसमें कच्चा sql भी शामिल है लेकिन मुझे नहीं लगता कि ORR ऑपरेशन करने के लिए ActiveRecord में कोई तरीका है। आपका सवाल एक शोर सवाल नहीं है।


40
यहां तक ​​कि अगर वहाँ कच्चे sql है - यह कथन मेरे लिए Arel की तुलना में बहुत स्पष्ट है। शायद DRYer भी।
जिबील

6
यदि आपको श्रृंखला बनाने की आवश्यकता है, तो अन्य Page.where("pages.column = ? or pages.other_column = ?", value, other_value)
तालिकाएं

1
और यह विफल हो जाता है अगर क्वेरी तालिकाओं को हटाती है। जब कि आलसी चमकते हैं।
डीजीएम

58

रेल / ActiveRecord का एक अद्यतन संस्करण इस वाक्यविन्यास का मूल रूप से समर्थन कर सकता है। यह समान दिखाई देगा:

Foo.where(foo: 'bar').or.where(bar: 'bar')

जैसा कि इस पुल अनुरोध में उल्लेख किया गया है https://github.com/rails/rails/pull/9052

अभी के लिए, बस निम्नलिखित कार्यों के साथ चिपके रहना बहुत अच्छा है:

Foo.where('foo= ? OR bar= ?', 'bar', 'bar')

अपडेट: https://github.com/rails/rails/pull/16052 के अनुसार यह orसुविधा रेल 5 में उपलब्ध होगी

अपडेट: फीचर को रेल्स 5 शाखा में विलय कर दिया गया है


2
orअब उपलब्ध है रेल 5 लेकिन इस तरह से लागू नहीं किया जाता है क्योंकि यह 1 तर्क पारित होने की उम्मीद करता है। यह एक Arel वस्तु की अपेक्षा करता है। स्वीकृत उत्तर देखें
El'Magnifico

2
orActiveRecord में विधि यह काम करती है यदि आप इसे सीधे उपयोग कर रहे हैं: लेकिन आपकी अपेक्षाओं को तोड़ सकता है यदि इसे उस दायरे में उपयोग किया जाता है जो तब जंजीर है।
जेरेमी सूची

@JeremyList ने जो कहा वह हाजिर है। वह मुझे कठिन है।
कोर्टमास

36

रेल्स ने हाल ही में इसे ActiveRecord में जोड़ा है। यह रेल 5 में जारी किया जा रहा है। पहले से ही मास्टर करने के लिए प्रतिबद्ध:

https://github.com/rails/rails/commit/9e42cf019f2417473e7dcbfcb885709fa2709f89

Post.where(column: 'something').or(Post.where(other: 'else'))

# => SELECT * FROM posts WHERE (column = 'something') OR (other = 'else)

23

रेल 5 एक orविधि के साथ आती है । (एल स्याही से प्रलेखन )

यह विधि किसी ActiveRecord::Relationऑब्जेक्ट को स्वीकार करती है। उदाहरण के लिए:

User.where(first_name: 'James').or(User.where(last_name: 'Scott'))

14

यदि आप सरणियों का उपयोग तर्कों के रूप में करना चाहते हैं, तो निम्न कोड रेल 4 में काम करता है:

query = Order.where(uuid: uuids, id: ids)
Order.where(query.where_values.map(&:to_sql).join(" OR "))
#=> Order Load (0.7ms)  SELECT "orders".* FROM "orders" WHERE ("orders"."uuid" IN ('5459eed8350e1b472bfee48375034103', '21313213jkads', '43ujrefdk2384us') OR "orders"."id" IN (2, 3, 4))

अधिक जानकारी: या नियम 4 में तर्क के रूप में सरणियों के साथ प्रश्न


9
या यह: Order.where(query.where_values.inject(:or))सभी तरह से उपयोग करने के लिए।
कैमरन मार्टिन

> या रेल में तर्क के रूप में सरणियों के साथ प्रश्न 4. उपयोगी लिंक! धन्यवाद!
ज़ेके फास्ट

7

MetaWhere प्लगइन पूरी तरह से अद्भुत है।

आसानी से OR और AND को मिलाएं, किसी भी एसोसिएशन में शर्तों को शामिल करें, और यहां तक ​​कि OUTER JOIN's निर्दिष्ट करें!

Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}

6

बस शर्तों में एक OR जोड़ें

Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])

4
यह रेल्स 2 के लिए अधिक वाक्यविन्यास है, और इसके लिए मुझे एक वर्ग स्ट्रिंग के कम से कम हिस्से को लिखना होगा।
ph33nixf1re

3

मैंने अभी इस प्लगइन को क्लाइंट के काम से निकाला है, जो आपको स्कोप्स को .or.पूर्व के साथ संयोजित करने देता है । Post.published.or.authored_by(current_user)। स्क्वील (मेटा खोज का नया कार्यान्वयन) भी बढ़िया है, लेकिन आपको या स्कैप्स नहीं करने देता है, इसलिए क्वेरी तर्क थोड़ा नया हो सकता है।


3

रेल + के साथ, एक और अधिक स्पष्ट तरीका:

# Table name: messages
#
# sender_id:    integer
# recipient_id: integer
# content:      text

class Message < ActiveRecord::Base
  scope :by_participant, ->(user_id) do
    left  = arel_table[:sender_id].eq(user_id)
    right = arel_table[:recipient_id].eq(user_id)

    where(Arel::Nodes::Or.new(left, right))
  end
end

पैदा करता है:

$ Message.by_participant(User.first.id).to_sql 
=> SELECT `messages`.* 
     FROM `messages` 
    WHERE `messages`.`sender_id` = 1 
       OR `messages`.`recipient_id` = 1

3

आप इसे कर सकते हैं:

Person.where("name = ? OR age = ?", 'Pearl', 24)

या अधिक सुरुचिपूर्ण, rails_or रत्न स्थापित करें और इसे पसंद करें:

Person.where(:name => 'Pearl').or(:age => 24)

-2

मैं जोड़ना चाहूंगा कि यह ActiveRecord की कई विशेषताओं को खोजने के लिए एक समाधान है। जबसे

.where(A: param[:A], B: param[:B])

ए और बी के लिए खोज करेंगे।


-4
Book.where.any_of(Book.where(:author => 'Poe'), Book.where(:author => 'Hemingway')

2
अपने उत्तर में कुछ स्पष्टीकरण जोड़ें
kvorobiev

1
मेरा मानना ​​है कि मैथ्यू activerecord_any_of मणि की बात कर रहा था जो इस सिंटैक्स के लिए समर्थन जोड़ता है।
DannyB

2
अगर सच है, धन्यवाद @DannyB उत्तर को इसका संदर्भ स्पष्ट करना चाहिए।
सेबेस्टियलोनो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.