OR এর পরিবর্তে OR এর সাথে স্কোপ কোয়েরিগুলি কীভাবে শৃঙ্খলাবদ্ধ?


137

আমি রেল 3, অ্যাক্টিভেকর্ড ব্যবহার করছি

আমি ভাবছি কীভাবে আমি AND এর পরিবর্তে OR বিবৃতি দিয়ে স্কোপগুলিকে শৃঙ্খলাবদ্ধ করতে পারি।

যেমন

Person.where(:name => "John").where(:lastname => "Smith")

এটি সাধারণত ফিরে আসে:

name = 'John' AND lastname = 'Smith'

তবে আমি চাই:

`name = 'John' OR lastname = 'Smith'

উত্তর:


107

আপনি করবেন

Person.where('name=? OR lastname=?', 'John', 'Smith')

এখনই নতুন এআর 3 সিনট্যাক্সের সাহায্যে অন্য কোনও ওআর সমর্থন নেই (এটি কোনও তৃতীয় পক্ষের রত্ন ব্যবহার না করে)।


21
এবং কেবল সুরক্ষার স্বার্থে এটি ব্যক্তিত্ব.কথা ("নাম =? বা শেষ নাম =?", 'জন', 'স্মিথ') হিসাবে প্রকাশ করা মূল্যবান
কেমব্রিজমাইক

6
এটি কি এখনও 4 রেলগুলিতে প্রযোজ্য? 4 রেল 4 এর চেয়ে ভাল আর কিছুই আসেনি?
ডোনাতো

11
পাগল 4, কিন্তু পাগল 5 কোন পরিবর্তন হবে .orসালে নির্মিত
চুন

3
এটি স্কোপ নয়, কেবল 2 যেখানে ক্লজ, বা খুব নির্দিষ্ট ক্ষেত্রের কেস। যদি আমি আরও জটিল স্কোপগুলি চেইন করতে চাই, উদাহরণস্বরূপ যোগদান করে।
সেপ্টেম্বর

2
5 টি রেল দিয়ে আপনি পার্সন.ওহেন ("নাম = 'জন'") বা (ব্যক্তি.ওহেনস ("শেষ নাম = 'স্মিথ'")) এর মতো কিছু করতে পারেন
shyam

59

এই টান অনুরোধ অনুসারে , রেল 5 এখন শৃঙ্খলা অনুসন্ধানের জন্য নিম্নলিখিত সিনট্যাক্স সমর্থন করে:

Post.where(id: 1).or(Post.where(id: 2))

এই রত্নের মাধ্যমে ails.২ রেলগুলিতে কার্যকারিতার একটি ব্যাকপোর্টও রয়েছে


48

আরেল ব্যবহার করুন

t = Person.arel_table

results = Person.where(
  t[:name].eq("John").
  or(t[:lastname].eq("Smith"))
)

1
এই ধরণের কোয়েরি পোস্টগ্রাগে ভাঙা যায় কিনা সে সম্পর্কে কেউ মন্তব্য করতে পারবেন?
অলিভিয়ার ল্যাকান

আরেল ডিবি-অজিনোস্টিক হওয়ার কথা।
সাইমন পেরেপেলিটসা

যদিও এটি দেখতে একটি ভাল ধারণা বলে মনে হচ্ছে, আর্য়েল একটি পাবলিক এপিআই নয় এবং এটি ব্যবহার করা আপনার অ্যাপ্লিকেশনটিকে অপ্রত্যাশিত উপায়ে ভেঙে দিতে পারে, সুতরাং আপনি যদি আরেল এপিআই এর বিবর্তনের দিকে মনোযোগ না দেন তবে আমি এর বিরুদ্ধে পরামর্শ দেব।
অলিভিয়ার ল্যাকান

7
@ অলিভিয়ারলান আরেল একটি পাবলিক এপিআই, বা আরও স্পষ্টভাবে, এটি একটি প্রকাশ করে exp অ্যাক্টিভ রেকর্ডটি এমন সুবিধাদির পদ্ধতিগুলি সরবরাহ করে যা এটি হুডের নীচে ব্যবহার করে, এটি নিজের নিজস্বভাবে ব্যবহার করা এটি সম্পূর্ণ বৈধ। এটি শব্দার্থক সংস্করণ অনুসরণ করে, সুতরাং আপনি যদি না প্রধান সংস্করণগুলি (3.XX => 4.xx) পরিবর্তন না করেন তবে ব্রেকিং পরিবর্তনগুলি নিয়ে চিন্তা করার দরকার নেই।
ধূসর

41

উপনিবেশগুলি সহায়তা করতে কেবল একই কলাম বা কোয়েরিগুলির জন্য অ্যারে বাক্য গঠনটি পোস্ট করা।

Person.where(name: ["John", "Steve"])

2
প্রশ্ন চেক নাম এবং স্মিথ বিরুদ্ধে জন বিরুদ্ধে LASTNAME
steven_noble

11
@ স্টিভেন_ নোবেল - এজন্যই আমি বা একই প্রশ্নের সাথে "একই কলামে" সাহসী হয়েছি। আমি মন্তব্যটি পুরোপুরি মুছতে পারি, তবে ভেবেছিলাম এটি "বা" এসও প্রশ্ন জিজ্ঞাসা করা লোকদের পক্ষে সহায়ক হবে।
daino3

38

রেলস 4 এর জন্য আপডেট

কোনও তৃতীয় পক্ষের রত্ন প্রয়োজন

a = Person.where(name: "John") # or any scope 
b = Person.where(lastname: "Smith") # or any scope 
Person.where([a, b].map{|s| s.arel.constraints.reduce(:and) }.reduce(:or))\
  .tap {|sc| sc.bind_values = [a, b].map(&:bind_values) }

পুরানো উত্তর

কোনও তৃতীয় পক্ষের রত্ন প্রয়োজন

Person.where(
    Person.where(:name => "John").where(:lastname => "Smith")
      .where_values.reduce(:or)
)

5
রিসোর্স এবং পদ্ধতির দিক থেকে এটিই ওপি'র প্রশ্নের একমাত্র শুদ্ধ উত্তর answer অন্যান্য উত্তরগুলির মধ্যে (ক) তৃতীয় পক্ষের এপিআইএস প্রয়োজন বা (খ) orএকটি পাঠ্য ব্লকের মধ্যে ইন্টারপোলটিং বা অন্যান্য অপারেটরগুলির প্রয়োজন , যার কোনটিই ওপির কোডে প্রতিফলিত হয় না।
অ্যালেনওয়ালি


4
...where_values.join(' OR ')আমার ক্ষেত্রে ব্যবহৃত
স্যাশ

2
.tap {|sc| sc.bind_values = [a, b].map(&:bind_values) }আপনার স্কোপগুলিতে বাধ্যবাধকতার প্রয়োজন হয় এমন কোনও ভেরিয়েবল না থাকলে আপনি সেই অংশটি বাদ দিতে পারেন।
ফতুহোকু

22

আপনি এসকিউএল স্টাফগুলির সাথে আপনার কোডটি মিশ্রিত করতে মেটাওহির মণি ব্যবহার করতে পারেন:

Person.where((:name => "John") | (:lastname => "Smith"))

3
+1 টি। মেটাওয়ের উত্তরসূরি একই লেখক দ্বারা কঙ্কিত
থিলো

22

যদি কেউ এর উত্তর আপডেটের সন্ধান করে তবে দেখে মনে হচ্ছে এটির ব্যয়গুলিতে প্রবেশ করার জন্য একটি বিদ্যমান টান অনুরোধ আছে: https://github.com/rails/rails/pull/9052

অ্যাক্টিভেকর্ডের জন্য @ j-mcnally এর বানর প্যাচকে ধন্যবাদ ( https://gist.github.com/j-mcnally/250eaaceef234dd8971b ) আপনি নিম্নলিখিতটি করতে পারেন:

Person.where(name: 'John').or.where(last_name: 'Smith').all

আরও মূল্যবান হ'ল এর সাথে স্কোপগুলি শৃঙ্খলাবদ্ধ করার ক্ষমতা OR:

scope :first_or_last_name, ->(name) { where(name: name.split(' ').first).or.where(last_name: name.split(' ').last) }
scope :parent_last_name, ->(name) { includes(:parents).where(last_name: name) }

তারপরে আপনি এমন সমস্ত ব্যক্তি খুঁজে পেতে পারেন যাঁর প্রথম বা শেষ নাম বা যার পিতামাতার শেষ নাম রয়েছে

Person.first_or_last_name('John Smith').or.parent_last_name('Smith')

এটি ব্যবহারের জন্য সেরা উদাহরণ নয়, তবে এটি কেবল প্রশ্নের সাথে ফিট করার চেষ্টা করছে।


2
এর জন্য আপনার কোন সংস্করণ বা রেলগুলি দরকার?
সাশ

3
এটি সর্বশেষতম আলোচনা এবং টানুন অনুরোধ যা এটি রেল কোরে পরিণত করবে তা এখানে পাওয়া যাবে: github.com/rails/rails/pull/16052 রেল 5.0 .orচেইন কার্যকারিতা আনুষ্ঠানিকভাবে প্রকাশের জন্য লক্ষ্যযুক্ত । আমি রেল> = 3.2 এ উল্লিখিত বানরের প্যাচটি ব্যবহার করতে সক্ষম হয়েছি; তবে আপনি আপনার কোডটিতে দীর্ঘস্থায়ী পরিবর্তনগুলি প্রবর্তন করতে 5 রেল অপেক্ষা করতে চাইতে পারেন।
কোডেনমেভ

1
হ্যাঁ, এটি একীভূত হয়েছিল এবং 5 টি রেলের সাথে মুক্তি
পেয়েছে

10

আমার জন্য (রেল ৪.২.৫) এটি কেবল এইভাবে কাজ করে:

{ where("name = ? or name = ?", a, b) }

8

আপনি যদি রেল ৩.০+ ব্যবহার করেন তবে এটি মেটাওহির পক্ষে ভাল প্রার্থী হবে, তবে এটি রেল ৩.১ এ কাজ করে না। পরিবর্তে আপনি কুঁচকে চেষ্টা করতে পারেন । এটি একই লেখক তৈরি করেছেন। আপনি কীভাবে একটি ওআর ভিত্তিক চেইন সম্পাদন করবেন তা এখানে রয়েছে:

Person.where{(name == "John") | (lastname == "Smith")}

আপনি অন্যান্য অনেক দুর্দান্ত জিনিসগুলির মধ্যে ম্যাসেজ করতে পারেন এবং AND / OR এর সাথে মিলিয়ে নিতে পারেন ।


8

রেলস / অ্যাক্টিভেকর্ডের একটি আপডেট সংস্করণ স্থানীয়ভাবে এই সিনট্যাক্সটিকে সমর্থন করতে পারে। এটি দেখতে অনুরূপ হবে:

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

এই টান অনুরোধ https://github.com/rails/rails/pull/9052 তে উল্লিখিত হিসাবে

আপাতত, কেবলমাত্র নিম্নলিখিত কাজগুলি দিয়ে আঁকানো দুর্দান্ত:

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


1
Foo.where(foo: 'bar1').or.where(bar: 'bar2')কাজ করে না. । Or.where ( 'bar2') Foo.where (বার): এটা Foo.where ( 'bar1' foo বিন্যাস) হওয়া উচিত
আনা মারিয়া মার্টিনেজ গোমস

6

রেল 4 + স্কোপ + আরেল

class Creature < ActiveRecord::Base
    scope :is_good_pet, -> {
        where(
            arel_table[:is_cat].eq(true)
            .or(arel_table[:is_dog].eq(true))
            .or(arel_table[:eats_children].eq(false))
        )
    }
end

আমি .ও এবং কোনও ভাগ্যের সাথে নামযুক্ত স্কোপগুলি শৃঙ্খলাবদ্ধ করার চেষ্টা করেছি, তবে এই বুলেটিয়ানস সেটগুলির সাথে কিছু খুঁজে পাওয়ার জন্য এটি কাজ করেছিল। এসকিউএল জেনারেট করে

SELECT 'CREATURES'.* FROM 'CREATURES' WHERE ((('CREATURES'.'is_cat' = 1 OR 'CREATURES'.'is_dog' = 1) OR 'CREATURES'.'eats_children' = 0))

4

রেল 4

scope :combined_scope, -> { where("name = ? or name = ?", 'a', 'b') }

4

আপনি যদি একটি সুযোগ সরবরাহ করতে চাইছেন (পুরো ডেটাসেটে স্পষ্টভাবে কাজ করার পরিবর্তে) এখানে আপনার রেল 5 কী করা উচিত তা এখানে:

scope :john_or_smith, -> { where(name: "John").or(where(lastname: "Smith")) }

বা:

def self.john_or_smith
  where(name: "John").or(where(lastname: "Smith"))
end

এটি সঠিক, তবে প্রযুক্তিগতভাবে স্ট্যাকওভারফ্লো . com/ a/ 42894753/1032882 একই জিনিসটির চেয়ে আরও আক্ষরিক উত্তর ।
রুডিঅনরেইলস

3

যদি আপনি "বা" বিবৃতিটি অন্তর্ভুক্ত করার জন্য ম্যানুয়ালি যেখানে ধারাটি লিখতে না পারেন (যেমন, আপনি দুটি স্কোপ একত্রিত করতে চান), আপনি ইউনিয়ন ব্যবহার করতে পারেন:

Model.find_by_sql("#{Model.scope1.to_sql} UNION #{Model.scope2.to_sql}")

(উত্স: অ্যাক্টিভেকর্ড ক্যোয়ারী ইউনিয়ন )

এটি যে কোনও প্রশ্নের সাথে মিলে সমস্ত রেকর্ড ফিরিয়ে দেবে। যাইহোক, এটি একটি অ্যারে দেয়, আরেল নয়। আপনি যদি সত্যিই একটি আরেল ফিরিয়ে দিতে চান তবে আপনি এই सारটিটি চেকআউট করুন: https://gist.github.com/j-mcnally/250eaaceef234dd8971b

এটি কাজটি করবে, যতক্ষণ না আপনি বানরের প্যাচিং রেলগুলি আপত্তি করেন।


2

এই সম্পর্কিত প্রশ্নগুলি দেখুন: এখানে , এখানে এবং এখানে

এই নিবন্ধ এবং এই মূল উত্তরের উপর ভিত্তি করে রেল 4 এর জন্য

Person
  .unscoped # See the caution note below. Maybe you want default scope here, in which case just remove this line.
  .where( # Begin a where clause
    where(:name => "John").where(:lastname => "Smith")  # join the scopes to be OR'd
    .where_values  # get an array of arel where clause conditions based on the chain thus far
    .inject(:or)  # inject the OR operator into the arels 
    # ^^ Inject may not work in Rails3. But this should work instead:
    .joins(" OR ")
    # ^^ Remember to only use .inject or .joins, not both
  )  # Resurface the arels inside the overarching query

শেষে নিবন্ধের সাবধানতা নোট করুন:

রেলগুলি 4.1+

রেলস 4.1 ডিফল্ট_স্কোপকে কেবল একটি নিয়মিত সুযোগ হিসাবে বিবেচনা করে। ডিফল্ট স্কোপ (যদি আপনার কোনও থাকে) যেখানে_ভ্যালু ফলাফলের সাথে অন্তর্ভুক্ত থাকে এবং ইনজেকশন (: বা) ডিফল্ট স্কোপ এবং আপনার চাকার মধ্যে যোগ বা বিবৃতি দেবে। এটা খারাপ.

এটি সমাধান করার জন্য, আপনাকে কেবল ক্যোয়ারীটি আনস্কোপ করতে হবে।


1

এটি একটি খুব সুবিধাজনক উপায় এবং এটি 5 রেলগুলিতে দুর্দান্ত কাজ করে:

Transaction
  .where(transaction_type: ["Create", "Correspond"])
  .or(
    Transaction.where(
      transaction_type: "Status",
      field: "Status",
      newvalue: ["resolved", "deleted"]
    )
  )
  .or(
    Transaction.where(transaction_type: "Set", field: "Queue")
  )

0

squeelমণি একটি অবিশ্বাস্যভাবে সহজ উপায় এই কাজ করা সম্ভব প্রদান করে (@ coloradoblue এর পদ্ধতি মত এই আমি ব্যবহার করার পূর্বে):

names = ["Kroger", "Walmart", "Target", "Aldi"]
matching_stores = Grocery.where{name.like_any(names)}

0

সুতরাং মূল প্রশ্নের উত্তর, আপনি 'বা' এর পরিবর্তে 'এবং' এর সাথে স্কোপগুলিতে যোগদান করতে পারেন এবং "আপনি পারবেন না" বলে মনে হচ্ছে। তবে আপনি কোডটি পুরোপুরি আলাদা স্কোপ বা কোয়েরি হ্যান্ড করতে পারেন যা কাজটি করে, বা অ্যাক্টিভেকর্ড থেকে আলাদা ফ্রেমওয়ার্ক ব্যবহার করতে পারে যেমন মেটাওয়ের বা স্কেল। আমার ক্ষেত্রে কার্যকর নয়

আমি পিজি_সার্ক দ্বারা উত্পন্ন স্কোপটি 'বা' করছি, যা নির্বাচনের চেয়ে কিছুটা বেশি করে তোলে, এতে এএসসি অর্ডার অন্তর্ভুক্ত করে, যা একটি পরিষ্কার ইউনিয়নকে গোলমাল করে। আমি একটি হস্তশিল্পের স্কোপ দিয়ে 'বা' এটি করতে চাই যা pg_search এ আমি করতে পারি না এমন জিনিসগুলি করে। সুতরাং আমি এটি এইভাবে করতে হবে।

Product.find_by_sql("(#{Product.code_starts_with('Tom').to_sql}) union (#{Product.name_starts_with('Tom').to_sql})")

অর্থাত স্কোপগুলিকে স্ক্যুলে পরিণত করুন, প্রত্যেকটির চারপাশে বন্ধনী স্থাপন করুন, তাদের একত্রিত করুন এবং তারপরে তৈরি এসকিএলএর সাহায্যে_বাই_এসকিএল সন্ধান করুন। এটি কিছুটা আবর্জনা, তবে এটি কাজ করে।

না, আমাকে বলবেন না যে আমি "বিরুদ্ধে: [: নাম,: কোড]" ব্যবহার করতে পারি পিজি_ সার্চে, আমি এটির মতো এটি করতে চাই তবে 'নাম' ক্ষেত্রটি হস্তান্তর, যা পিজি_সার্চ পরিচালনা করতে পারে না এখনো. সুতরাং নামের সাথে স্কোপটি হাতে তৈরি করতে হবে এবং তারপরে পিজি_সার্চ স্কোপের সাথে মিলিত হতে হবে।


-2
names = ["tim", "tom", "bob", "alex"]
sql_string = names.map { |t| "name = '#{t}'" }.join(" OR ")
@people = People.where(sql_string)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.