Arel और Rails में LIKE क्वेरी कैसे करें?


115

मैं कुछ ऐसा करना चाहता हूं:

SELECT * FROM USER WHERE NAME LIKE '%Smith%';

अरेल में मेरा प्रयास:

# params[:query] = 'Smith'
User.where("name like '%?%'", params[:query]).to_sql

हालाँकि, यह बन जाता है:

SELECT * FROM USER WHERE NAME LIKE '%'Smith'%';

Arel क्वेरी स्ट्रिंग 'Smith' को सही तरीके से लपेटता है, लेकिन क्योंकि यह एक LIKE स्टेटमेंट है जो काम नहीं करता है।

Arel में एक LIKE क्वेरी कैसे की जाती है?

पीएस बोनस - मैं वास्तव में टेबल पर दो फ़ील्ड स्कैन करने की कोशिश कर रहा हूं, नाम और विवरण दोनों, यह देखने के लिए कि क्या क्वेरी के लिए कोई मैच हैं। वह कैसे काम करेगा?


1
मैंने बोनस के लिए arel जवाब अपडेट किया।
पेड्रो रोलो

जवाबों:


275

यह है कि आप किस तरह से क्वेरी करते हैं:

users = User.arel_table
User.where(users[:name].matches("%#{user_name}%"))

पुनश्च:

users = User.arel_table
query_string = "%#{params[query]}%"
param_matches_string =  ->(param){ 
  users[param].matches(query_string) 
} 
User.where(param_matches_string.(:name)\
                       .or(param_matches_string.(:description)))

10
उपयोग करने के विपरीत where("name like ?", ...), यह दृष्टिकोण विभिन्न डेटाबेस में अधिक पोर्टेबल है। उदाहरण के लिए, यह ILIKEPostgres db के विरुद्ध क्वेरी में उपयोग किए जाने के परिणामस्वरूप होगा ।
dkobozev 21

20
यह SQL इंजेक्शन के खिलाफ संरक्षित है?
sren

7
यह SQL इंजेक्शन के खिलाफ पूरी तरह से रक्षा नहीं करता है। "%" में user_name सेट करने का प्रयास करें। क्वेरी मैचों
ट्रैविस -144 पर

5
मैंने सीधे params का उपयोग करके sql इंजेक्षन करने User.where(users[:name].matches("%#{params[:user_name]}%"))की कोशिश की, मैंने कोशिश की TRUNCATE users;और इस तरह के अन्य प्रश्नों और sql पक्ष पर कुछ भी नहीं हुआ। मुझे सुरक्षित लगता है।
18

5
.gsub(/[%_]/, '\\\\\0')MySql वाइल्डकार्ड चार्ट से बचने के लिए उपयोग करें ।
एर्कोलिनो

116

प्रयत्न

User.where("name like ?", "%#{params[:query]}%").to_sql

पुनश्च।

q = "%#{params[:query]}%"
User.where("name like ? or description like ?", q, q).to_sql

Aaand यह एक लंबा समय रहा है, लेकिन @ cgg5207 ने एक संशोधन जोड़ा (ज्यादातर उपयोगी यदि आप लंबे नाम वाले या कई लंबे नाम वाले मापदंडों को खोजने जा रहे हैं या आप टाइप करने के लिए बहुत आलसी हैं)

q = "%#{params[:query]}%"
User.where("name like :q or description like :q", :q => q).to_sql

या

User.where("name like :q or description like :q", :q => "%#{params[:query]}%").to_sql

9
कैसे पता %लगाया स्ट्रिंग में भागने के लिए नहीं पता है ? ऐसा लगता है कि यदि आप केवल एक तरफा वाइल्डकार्ड चाहते थे, तो उपयोगकर्ता को क्वेरी मान प्रस्तुत करने से रोकना नहीं है, जिसमें %दोनों सिरों को शामिल किया गया है (मुझे पता है कि व्यवहार में, रेल्स %एक क्वेरी स्ट्रिंग में दिखाई देने से रोकता है, लेकिन ऐसा लगता है ActiveRecord स्तर पर इसके विरुद्ध सुरक्षा होनी चाहिए)।
स्टीवन

8
क्या यह SQL इंजेक्शन हमलों के लिए संवेदनशील नहीं है?
बेहरंग सईदज़ादेह

7
@Behrang no 8) User.where ("% @ {params [: query]}% या% # {params [: query]}%" जैसे विवरण))। To_sql असुरक्षित होगा, लेकिन, प्रारूप में मैं दिखाता हूं। , रेल से बच
निकलते हैं परम

ऑफटॉपिक के लिए क्षमा करें। मेरे पास sql git of method to_sqlया arel manager है, db पर sql को कैसे निष्पादित करें?
Мал

मॉडल। वे (to_sql_result)
पेड्रो रोलो

4

रूबेन मलबाई के जवाब को पैरामीटर बाइंडिंग का उपयोग करने के लिए और छोटा किया जा सकता है:

User.where("name like :kw or description like :kw", :kw=>"%#{params[:query]}%").to_sql
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.