এই নিবন্ধটি কোরিয়ান ভাষায়ও উপলব্ধ, ধন্যবাদ Soonsang Hong!
রেলের স্কোপগুলি আপনার পছন্দের রেকর্ডগুলি খুঁজে পাওয়া সহজ করে তোলে:
class Review < ActiveRecord::Base
belongs_to :restaurant
scope :positive, -> { where("rating > 3.0") }
end
irb(main):001:0> Restaurant.first.reviews.positive.count
Restaurant Load (0.4ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 1
(0.6ms) SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
=> 5
কিন্তু আপনি যদি তাদের ব্যাপারে সতর্ক না হন, তাহলে আপনি আপনার অ্যাপের কার্যক্ষমতাকে মারাত্মকভাবে ক্ষতিগ্রস্ত করবেন।
কেন? আপনি সত্যিই একটি সুযোগ প্রিলোড করতে পারবেন না৷৷ সুতরাং আপনি যদি কয়েকটি রেস্তোরাঁকে তাদের ইতিবাচক পর্যালোচনা সহ দেখানোর চেষ্টা করেন:
irb(main):001:0> restauraunts = Restaurant.first(5)
irb(main):002:0> restauraunts.map do |restaurant|
irb(main):003:1* "#{restaurant.name}: #{restaurant.reviews.positive.length} positive reviews."
irb(main):004:1> end
Review Load (0.6ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
Review Load (0.5ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 2 AND (rating > 3.0)
Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 3 AND (rating > 3.0)
Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 4 AND (rating > 3.0)
Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 5 AND (rating > 3.0)
=> ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."]
হ্যাঁ, এটি একটি N+1 প্রশ্ন। ধীরগতির রেল অ্যাপের সবচেয়ে বড় কারণ।
যদিও, আপনি যদি সম্পর্কটিকে অন্যভাবে চিন্তা করেন তবে আপনি এটি বেশ সহজে ঠিক করতে পারেন৷
স্কোপগুলিকে অ্যাসোসিয়েশনে রূপান্তর করুন
আপনি যখন রেল অ্যাসোসিয়েশন পদ্ধতি ব্যবহার করেন, যেমন belongs_to
এবং has_many
, আপনার মডেল সাধারণত এই মত দেখায়:
class Restaurant < ActiveRecord::Base
has_many :reviews
end
কিন্তু আপনি যদি ডকুমেন্টেশন চেক আউট করেন, আপনি দেখতে পাবেন যে তারা আরও কিছু করতে পারে। আপনি সেই পদ্ধতিগুলিতে অন্যান্য প্যারামিটারগুলি পাস করতে পারেন এবং তারা কীভাবে কাজ করে তা পরিবর্তন করতে পারেন৷
scope
সবচেয়ে দরকারী এক. এটি ঠিক scope
এর মত কাজ করে আগের থেকে:
class Restaurant < ActiveRecord::Base
has_many :reviews
has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review"
end
irb(main):001:0> Restaurant.first.positive_reviews.count
Restaurant Load (0.2ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 1
(0.4ms) SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
=> 5
এখন, আপনি includes
এর সাথে আপনার নতুন অ্যাসোসিয়েশন প্রিলোড করতে পারেন :
irb(main):001:0> restauraunts = Restaurant.includes(:positive_reviews).first(5)
Restaurant Load (0.3ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 5
Review Load (1.2ms) SELECT `reviews`.* FROM `reviews` WHERE (rating > 3.0) AND `reviews`.`restaurant_id` IN (1, 2, 3, 4, 5)
irb(main):002:0> restauraunts.map do |restaurant|
irb(main):003:1* "#{restaurant.name}: #{restaurant.positive_reviews.length} positive reviews."
irb(main):004:1> end
=> ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."]
6 টি এসকিউএল কলের পরিবর্তে, আমরা শুধুমাত্র দুটি করেছি।
(class_name
ব্যবহার করে , একই বস্তুর সাথে আপনার একাধিক অ্যাসোসিয়েশন থাকতে পারে। এটি প্রায়শই কাজে আসে।)
ডুপ্লিকেশন সম্পর্কে কি?
এখানে এখনও একটি সমস্যা হতে পারে. where("rating > 3.0")
এখন আপনার রেস্টুরেন্ট ক্লাসে আছে. যদি আপনি পরে ইতিবাচক পর্যালোচনাগুলিকে rating > 3.5
এ পরিবর্তন করেন , আপনাকে এটি দুবার আপডেট করতে হবে!
এটি আরও খারাপ হয়ে যায়:আপনি যদি একজন ব্যক্তির রেখে যাওয়া সমস্ত ইতিবাচক পর্যালোচনাগুলিও পেতে চান, তাহলে আপনাকে ব্যবহারকারী শ্রেণিতেও সেই সুযোগটি নকল করতে হবে:
class User < ActiveRecord::Base
has_many :reviews
has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review"
end
এটা খুব শুষ্ক নয়।
যদিও এর কাছাকাছি একটি সহজ উপায় আছে। where
এর ভিতরে , আপনি positive
ব্যবহার করতে পারেন স্কোপ আপনি পর্যালোচনা ক্লাসে যোগ করেছেন:
class Restaurant < ActiveRecord::Base
has_many :reviews
has_many :positive_reviews, -> { positive }, class_name: "Review"
end
এইভাবে, ধারণা একটি পর্যালোচনা একটি ইতিবাচক পর্যালোচনা এখনও শুধুমাত্র একটি জায়গায় আছে.
সুযোগ মহান. সঠিক জায়গায়, তারা আপনার ডেটা অনুসন্ধান করা সহজ এবং মজাদার করতে পারে। কিন্তু আপনি যদি N+1 প্রশ্নগুলি এড়াতে চান, তাহলে আপনাকে সেগুলির ব্যাপারে সতর্ক থাকতে হবে৷
৷সুতরাং, যদি একটি সুযোগ আপনাকে সমস্যা সৃষ্টি করতে শুরু করে, তাহলে এটিকে একটি অ্যাসোসিয়েশনে মুড়ে দিন এবং এটি প্রিলোড করুন . এটি আর বেশি কাজ নয়, এবং এটি আপনাকে একগুচ্ছ SQL কল সংরক্ষণ করবে।