ruby on rails - রেল 3: র্যান্ডম রেকর্ড পান




ruby-on-rails ruby-on-rails-3 (10)

সুতরাং, আমি Rails 2 এ একটি র্যান্ডম রেকর্ড খুঁজে পেতে বেশ কয়েকটি উদাহরণ খুঁজে পেয়েছি - পছন্দসই পদ্ধতিটি মনে হচ্ছে:

Thing.find :first, :offset => rand(Thing.count)

একটি নববধূ কিছু হচ্ছে আমি Rails 3 মধ্যে নতুন সার্চ সিনট্যাক্স ব্যবহার করে কিভাবে এটি নির্মিত হতে পারে তা নিশ্চিত নই।

সুতরাং, একটি র্যান্ডম রেকর্ড খুঁজে পেতে "Rails 3 ওয়ে" কি?


Postgres ব্যবহার করে

User.limit(5).order("RANDOM()")

মাইএসকিউএল ব্যবহার করে

User.limit(5).order("RAND()")

উভয় ক্ষেত্রেই আপনি ব্যবহারকারী টেবিল থেকে এলোমেলোভাবে 5 রেকর্ড নির্বাচন করছেন। এখানে কনসোল প্রদর্শিত প্রকৃত SQL ক্যোয়ারী।

SELECT * FROM users ORDER BY RANDOM() LIMIT 5


আমি বড় বড় টেবিলের উপর ভাল সঞ্চালনের জন্য এটি একটি রেলের 3 মণি তৈরি করেছি এবং আপনাকে চেইন সম্পর্ক এবং স্কোপগুলি করার অনুমতি দেয়:

https://github.com/spilliton/randumb

(সম্পাদন করুন): আমার মণির ডিফল্ট আচরণ মূলত উপরের মত একই পদ্ধতি ব্যবহার করে, তবে আপনার যদি পুরানো পদ্ধতি ব্যবহার করতে চান তবে আপনার কাছে বিকল্প আছে :)


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

@question1 = Question.where(:lesson_id => params[:lesson_id]).shuffle[1]

এবং এটা আমার জন্য ভাল কাজ করছে। আমি এই থেকে বড় DBs জন্য পারফরমেন্স কিভাবে একটি ছোট অ্যাপ্লিকেশন হয় কিভাবে কথা বলতে পারে না।


এটি আমার জন্য খুব দরকারী ছিল তবে আমার আরও কিছুটা নমনীয়তা দরকার, তাই আমি যা করেছি তা হল:

কেস 1: একটি র্যান্ডম রেকর্ড উৎস খোঁজা : trevor তুরস্ক সাইট
এই Thing.rb মডেল যোগ করুন

def self.random
    ids = connection.select_all("SELECT id FROM things")
    find(ids[rand(ids.length)]["id"].to_i) unless ids.blank?
end

তারপর আপনার নিয়ামক আপনি এই মত কিছু কল করতে পারেন

@thing = Thing.random

কেস 2: একাধিক র্যান্ডম রেকর্ড খোঁজা (কোন পুনরাবৃত্তি) উৎস: মনে রাখা যাবে না
আমি কোন পুনরাবৃত্তি সঙ্গে 10 র্যান্ডম রেকর্ড খুঁজে পেতে প্রয়োজন তাই এই আমি কাজ পাওয়া কি
আপনার নিয়ামক মধ্যে:

thing_ids = Thing.find( :all, :select => 'id' ).map( &:id )
@things = Thing.find( (1..10).map { thing_ids.delete_at( thing_ids.size * rand ) } )

এটি 10 ​​টি র্যান্ডম রেকর্ড খুঁজে পাবে, তবে উল্লেখযোগ্য যে ডাটাবেসটি যদি বিশেষভাবে বড় হয় (লক্ষ লক্ষ রেকর্ড), এটি আদর্শ হবে না এবং কর্মক্ষমতা বাধাগ্রস্ত হবে। আমার জন্য যথেষ্ট ছিল কয়েক হাজার রেকর্ড পর্যন্ত ভাল সঞ্চালন করা হবে।


এলোমেলোভাবে একটি তালিকা থেকে একটি আইটেম বাছাই জন্য রুবি পদ্ধতি sample । ActiveRecord এর জন্য দক্ষ sample তৈরি করতে চান এবং পূর্ববর্তী উত্তরগুলির উপর ভিত্তি করে আমি ব্যবহার করেছি:

module ActiveRecord
  class Base
    def self.sample
      offset(rand(size)).first
    end
  end
end

আমি lib/ext/sample.rb এটিকে রেখে দিয়ে config/initializers/monkey_patches.rb এ এটি দিয়ে লোড config/initializers/monkey_patches.rb :

Dir[Rails.root.join('lib/ext/*.rb')].each { |file| require file }

টেবিল থেকে একাধিক র্যান্ডম রেকর্ড পেতে একটি খুব সহজ উপায়। এই 2 সস্তা প্রশ্নের তোলে।

Model.where(id: Model.pluck(:id).sample(3))

আপনি চান যে র্যান্ডম রেকর্ড সংখ্যা "3" পরিবর্তন করতে পারেন।


পোস্ট উত্তর অনেক আসলে বড় টেবিল (1+ মিলিয়ন সারি) উপর ভাল সঞ্চালন করবে না। র্যান্ডম ক্রমটি দ্রুত কয়েক সেকেন্ড সময় নেয় এবং টেবিলের উপর গণনা করা খুব দীর্ঘ সময় নেয়।

এই অবস্থানে আমার জন্য ভাল কাজ করে এমন একটি সমাধানটি যেখানে RANDOM() ব্যবহার করে সেটি হল:

Thing.where('RANDOM() >= 0.9').take

এক মিলিয়ন সারি সহ একটি টেবিলে, এই প্রশ্নটি সাধারণত ২ মিমি কম থাকে।


র্যান্ডম রেকর্ডগুলির জন্য এই মোমটিকে দৃঢ়ভাবে সুপারিশ করুন, যা বিশেষভাবে টেবিলে প্রচুর ডাটা সারির সাথে ডিজাইন করা হয়েছে:

https://github.com/haopingfan/quick_random_records

অন্যান্য অন্যান্য উত্তর এই মণি ছাড়া বড় ডাটাবেসের সাথে খারাপভাবে সঞ্চালন করে:

  1. quick_random_records শুধুমাত্র 4.6ms সম্পূর্ণ খরচ।

  1. গ্রহণযোগ্য উত্তর User.order('RAND()').limit(10) 733.0ms

  1. offset পদ্ধতির সম্পূর্ণ 245.4ms খরচ।

  1. User.all.sample(10) পদ্ধতির খরচ 573.4ms

দ্রষ্টব্য: আমার টেবিলে শুধুমাত্র 120,000 ব্যবহারকারী রয়েছে। আপনার কাছে আরো রেকর্ড, কর্মক্ষমতা পার্থক্য আরো বিরাট হবে।

হালনাগাদ:

550,000 সারি সঙ্গে টেবিলের উপর সঞ্চালন

  1. Model.where(id: Model.pluck(:id).sample(10)) খরচ 1384.0ms

  1. gem: quick_random_records শুধুমাত্র 6.4ms সম্পূর্ণ খরচ


Thing.first(:order => "RANDOM()") # For MySQL :order => "RAND()", - thanx, @DanSingerman
# Rails 3
Thing.order("RANDOM()").first

অথবা

Thing.first(:offset => rand(Thing.count))
# Rails 3
Thing.offset(rand(Thing.count)).first

প্রকৃতপক্ষে, Rails 3 সমস্ত উদাহরণ কাজ করবে। কিন্তু অর্ডার RANDOM ব্যবহার করে বড় টেবিলগুলির জন্য বেশ ধীর কিন্তু আরো SQL-style

UPD। আপনি সূচীকৃত কলামে নিম্নলিখিত কৌশলটি ব্যবহার করতে পারেন (PostgreSQL সিনট্যাক্স):

select * 
from my_table 
where id >= trunc(
  random() * (select max(id) from my_table) + 1
) 
order by id 
limit 1;





random