অ্যাক্টিভেকর্ড / রেলগুলির সাথে কীভাবে একটি নোট ইন প্রশ্নটি প্রকাশ করবেন?


207

কেবল এটি আপডেট করার জন্য যেহেতু মনে হয় প্রচুর লোকেরা এতে আসেন, আপনি যদি ট্রেল 4 এবং ভিনি ভিডিভিচির উত্তরগুলি দেখুন 4 টি আপনি রেল ব্যবহার করছেন।

Topic.where.not(forum_id:@forums.map(&:id))

Topic.where(published:true).where.not(forum_id:@forums.map(&:id))

আমি আশা করছি এমন একটি সহজ সমাধান রয়েছে যা জড়িত না find_by_sql, যদি না হয় তবে আমি অনুমান করি যে এটি কাজ করতে হবে।

আমি এই নিবন্ধটি খুঁজে পেয়েছি যা এটি উল্লেখ করে:

Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })

যা হিসাবে একই

SELECT * FROM topics WHERE forum_id IN (<@forum ids>)

আমি ভাবছি NOT INযে এর সাথে করার মতো কোনও উপায় আছে কিনা :

SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)

3
একটি এফওয়াইআই হিসাবে, ড্যাটাম্পার নট ইন-এর জন্য নির্দিষ্ট সমর্থন পেয়েছে। উদাহরণ:Person.all(:name.not => ['bob','rick','steve'])
মার্ক টমাস

1
অজ্ঞ হওয়ার জন্য দুঃখিত, তবে ডেটামেপার কী? রেল 3 এর যে অংশ?
টবি জয়েনার

2
ডেটা ম্যাপার ডেটা সংরক্ষণের একটি বিকল্প উপায়, এটি একটি ভিন্ন কাঠামোর সাথে সক্রিয় রেকর্ডকে প্রতিস্থাপন করে এবং তারপরে আপনি নিজের মডেল সম্পর্কিত স্টাফ যেমন কোয়েরিগুলি আলাদাভাবে লেখেন।
মাইকেল ডুরান্ট

উত্তর:


313

রেল 4+:

Article.where.not(title: ['Rails 3', 'Rails 5']) 

রেল 3:

Topic.where('id NOT IN (?)', Array.wrap(actions))

যেখানে actionsঅ্যারে রয়েছে:[1,2,3,4,5]


1
সর্বশেষ সক্রিয় রেকর্ড ক্যোয়ারী মডেলটির সাথে এটি সঠিক পদ্ধতি
নেভিয়ার

5
@ নিউ আলেকজান্দ্রিয়া ঠিক আছে, তাই আপনাকে এরকম কিছু করতে হবে Topic.where('id NOT IN (?)', (actions.empty? ? '', actions)। এটি এখনও শূন্য হয়ে যেতে পারে তবে আমি দেখতে পাচ্ছি যে আপনি যে অ্যারেটি দিয়ে যান সেটি সাধারণত একটি ফিল্টার দ্বারা উত্পাদিত হয় []যা খুব কম সময়ে ফিরে আসে এবং কখনই শূন্য হয় না। আমি অ্যাক্টিভ রেকর্ডের শীর্ষে ডিএসএল, স্কোয়েল চেক আউট করার পরামর্শ দিচ্ছি। তারপরে আপনি এটি করতে পারেন Topic.where{id.not_in actions}:, শূন্য / খালি / বা অন্যথায়।
ডানেউ

6
@ উদ্যানু কেবলমাত্র অদলবদল .empty?করুন .blank?এবং আপনি শূন্য-প্রমাণ হন
কল্লিন

(ক্রিয়া .empty?? '', ক্রিয়াকলাপ) @ দানাউয়ের দ্বারা হওয়া উচিত (ক্রিয়াকলাপ?? '': ক্রিয়া)
মার্সেল সালাতে

3
Article.where.not (শিরোনাম: [ 'পাগল 3', 'পাগল 5']) জন্য যেতে 4 স্বরলিপি পাগল
তাল

152

এফওয়াইআই, চারটি কারাগারে আপনি notবাক্য গঠন ব্যবহার করতে পারেন :

Article.where.not(title: ['Rails 3', 'Rails 5'])

11
পরিশেষে! এগুলিকে অন্তর্ভুক্ত করতে এতক্ষণ কী লাগল? :)
ডোমিনিক গলটারম্যান

50

আপনি এর মতো কিছু চেষ্টা করতে পারেন:

Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.map(&:id)])

আপনার প্রয়োজন হতে পারে @forums.map(&:id).join(',')। আমি মনে করতে পারছি না যে রেইলগুলি একটি সিএসভি তালিকায় যুক্তিযুক্ত হবে যদি তা অনুমিত হয়।

আপনি এটি করতে পারেন:

# in topic.rb
named_scope :not_in_forums, lambda { |forums| { :conditions => ['forum_id not in (?)', forums.select(&:id).join(',')] }

# in your controller 
Topic.not_in_forums(@forums)

50

আরেল ব্যবহার:

topics=Topic.arel_table
Topic.where(topics[:forum_id].not_in(@forum_ids))

বা, যদি অগ্রাধিকার দেওয়া হয়:

topics=Topic.arel_table
Topic.where(topics[:forum_id].in(@forum_ids).not)

এবং 4 রেল থেকে:

topics=Topic.arel_table
Topic.where.not(topics[:forum_id].in(@forum_ids))

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

@forum_ids = Forum.where(/*whatever conditions are desirable*/).select(:id)

এইভাবে আপনি একক ক্যোয়ারিতে সমস্ত কিছু পান: এরকম কিছু:

select * from topic 
where forum_id in (select id 
                   from forum 
                   where /*whatever conditions are desirable*/)

এছাড়াও লক্ষ্য করুন যে অবশেষে আপনি এটি করতে চান না, বরং একটি যোগ দিন - কী আরও কার্যকর হতে পারে।


2
একটি যোগদান আরও দক্ষ হতে পারে, তবে অগত্যা নয়। ব্যবহার নিশ্চিত করুন EXPLAIN!
জেমস

20

@ ট্রুং ল ê উত্তরটি প্রসারিত করতে, 4 রেলগুলিতে আপনি নিম্নলিখিতটি করতে পারেন:

Topic.where.not(forum_id:@forums.map(&:id))

এবং আপনি এটিকে আরও একধাপ এগিয়ে নিয়ে যেতে পারেন। আপনার যদি কেবলমাত্র প্রকাশিত টপিকগুলির জন্য প্রথমে ফিল্টার করতে হয় এবং তারপরে আপনি চান না এমন আইডিগুলি ফিল্টার করতে পারেন তবে আপনি এটি করতে পারেন:

Topic.where(published:true).where.not(forum_id:@forums.map(&:id))

4 রেল এত সহজ করে তোলে!


12

গৃহীত সমাধানটি @forumsফাঁকা থাকলে ব্যর্থ হয়। এই কাজটি করতে আমাকে করতে হয়েছিল

Topic.find(:all, :conditions => ['forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id))])

বা, যদি রেলগুলি 3+ ব্যবহার করে থাকে:

Topic.where( 'forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id)) ).all

4

উপরের উত্তরগুলির বেশিরভাগটিই আপনার পর্যাপ্ত হওয়া উচিত তবে আপনি যদি এই জাতীয় ভবিষ্যদ্বাণীপূর্ণ এবং জটিল সংমিশ্রণগুলি আরও অনেক কিছু করে থাকেন তবে স্কেল পরীক্ষা করে দেখুন । আপনি এর মতো কিছু করতে সক্ষম হবেন:

Topic.where{{forum_id.not_in => @forums.map(&:id)}}
Topic.where{forum_id.not_in @forums.map(&:id)} 
Topic.where{forum_id << @forums.map(&:id)}

2

আপনি আর্নি মিলার দ্বারা মেটা_ কোথাও প্লাগইনটি দেখতে চান । আপনার এসকিউএল বিবৃতি:

SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)

... এই মত প্রকাশ করা যেতে পারে:

Topic.where(:forum_id.nin => @forum_ids)

রেইলকাস্টসের রায়ান বেটস মেটাওয়ের ব্যাখ্যা করে একটি দুর্দান্ত স্ক্রিনকাস্ট তৈরি করেছে

আপনি যা সন্ধান করছেন এটি এটি যদি নিশ্চিত না তবে আমার চোখের কাছে এটি এম্বেডড এসকিউএল কোয়েরির চেয়ে অবশ্যই ভাল দেখায়।


2

মূল পোস্টটি সুনির্দিষ্টভাবে সংখ্যাসূচক আইডি ব্যবহার করে উল্লেখ করেছে, তবে আমি এখানে স্ট্রিংগুলির অ্যারের সাথে একটি নোট IN করার জন্য বাক্য গঠনটি অনুসন্ধান করতে এসেছি।

অ্যাক্টিভেকর্ডটি আপনার পক্ষেও দুর্দান্তভাবে এটি পরিচালনা করবে:

Thing.where(['state NOT IN (?)', %w{state1 state2}])

1

এই ফোরাম আইডির ব্যবহারিক উপায়ে কাজ করা যেতে পারে? যেমন আপনি এই ফোরামগুলি একরকম খুঁজে পেতে পারেন - যদি এটি হয় তবে আপনার মতো কিছু করা উচিত

Topic.all(:joins => "left join forums on (forums.id = topics.forum_id and some_condition)", :conditions => "forums.id is null")

যা এসকিউএল করার চেয়ে বেশি দক্ষ হবে not in


1

এই উপায়টি পঠনযোগ্যতার জন্য অনুকূল করে তবে এটি ডাটাবেস প্রশ্নের ক্ষেত্রে কার্যকর নয়:

# Retrieve all topics, then use array subtraction to
# find the ones not in our list
Topic.all - @forums.map(&:id)

0

আপনি আপনার অবস্থার ক্ষেত্রে স্কয়ার ব্যবহার করতে পারেন:

Topic.find(:all, :conditions => [ "forum_id NOT IN (?)", @forums.map(&:id)])

0

পিঞ্জিব্যাকিং অফ জন্নিই:

Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.pluck(:id)])

উপাদানগুলির উপর ম্যাপিংয়ের পরিবর্তে প্ল্যাক ব্যবহার করা

Railsconf 2012 এর মাধ্যমে পাওয়া গেছে 10 টি জিনিস যা আপনি জানতেন না যে রেলগুলি করতে পারে


0

যখন আপনি একটি ফাঁকা অ্যারে জিজ্ঞাসা করেন যেখানে ব্লকের অ্যারেটিতে "<< 0" যুক্ত করুন যাতে এটি "NULL" ফেরত না এবং কোয়েরিটি ভঙ্গ করে।

Topic.where('id not in (?)',actions << 0)

যদি ক্রিয়াগুলি খালি বা ফাঁকা অ্যারে হতে পারে।


1
সতর্কতা: এটি আসলে অ্যারেতে 0 যুক্ত করে, তাই এটি আর খালি নেই। এটি অ্যারে সংশোধন করার পার্শ্ব-প্রতিক্রিয়াও রয়েছে - আপনি যদি পরে এটি ব্যবহার করেন তবে ডাবল বিপদ। এটি যদি অন্যথায় মুড়ে ফেলা যায় এবং শীর্ষ প্রান্তের ক্ষেত্রে টপিক.নোন / সমস্ত ব্যবহার করা ভাল
টেড পেনিংস

একটি নিরাপদ উপায়:Topic.where("id NOT IN (?)", actions.presence || [0])
ওয়েস্টন গাঙ্গার

0

স্কেল ব্যবহার করে রেল 4 র একটি সাবকিউরি ব্যবহার করে এখানে আরও জটিল "নন" ক্যোয়ারী রয়েছে। সমতুল্য স্কয়ারের তুলনায় অবশ্যই খুব ধীর, তবে ওহে, এটি কাজ করে।

    scope :translations_not_in_english, ->(calmapp_version_id, language_iso_code){
      join_to_cavs_tls_arr(calmapp_version_id).
      joins_to_tl_arr.
      where{ tl1.iso_code == 'en' }.
      where{ cavtl1.calmapp_version_id == my{calmapp_version_id}}.
      where{ dot_key_code << (Translation.
        join_to_cavs_tls_arr(calmapp_version_id).
        joins_to_tl_arr.    
        where{ tl1.iso_code == my{language_iso_code} }.
        select{ "dot_key_code" }.all)}
    }

সুযোগের প্রথম 2 টি পদ্ধতি হ'ল অন্যান্য স্কোপ যা অ্যালিয়াস ক্যাভটল 1 এবং টিএল 1 ঘোষণা করে। << স্কুয়েলে অপারেটর নয়।

আশা করি এটি কাউকে সাহায্য করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.