2011-01-16 16 views
11

मेरे पास एक ब्लॉग है। मेरे सूचकांक पेज पर, मैं सभी ब्लॉग पोस्ट खींचता हूं। प्रत्येक ब्लॉग पोस्ट के लिए, मैं उस पोस्ट पर टिप्पणियों की संख्या गिनता हूं। इससे एन + 1 समस्या होती है।रेल एसक्यूएल COUNT एन + 1 अक्षमता

SELECT "blog_posts".* FROM "blog_posts" WHERE ("blog_posts"."published" = 't') ORDER BY published_at DESC 
SELECT "users".* FROM "users" WHERE ("users"."id" IN (1, 2, 3)) 
SELECT COUNT(*) FROM "blog_comments" WHERE ("blog_comments".blog_post_id = 10) 
SELECT COUNT(*) FROM "blog_comments" WHERE ("blog_comments".blog_post_id = 9) 
SELECT COUNT(*) FROM "blog_comments" WHERE ("blog_comments".blog_post_id = 8) 
SELECT COUNT(*) FROM "blog_comments" WHERE ("blog_comments".blog_post_id = 2) 
SELECT COUNT(*) FROM "blog_comments" WHERE ("blog_comments".blog_post_id = 7) 

वहाँ रेल में एक तरह से उसी तरह मैं उन (एसक्यूएल लाइन 2) शामिल हैं में COUNT शामिल करने के लिए है: मेरे प्रश्नों ऐसा नज़र?

उत्तर

21

आप काउंटर कैश का उपयोग कर सकते हैं: http://guides.rubyonrails.org/association_basics.html#counter_cache

"इस घोषणा के साथ, रेल कैश मूल्य नवीनतम जानकारी रखना, और फिर आकार विधि के जवाब में कि मान।"

class BlogPost < ActiveRecord::Base 
    has_many :blog_comments 
end 

class BlogComment < ActiveRecord::Base 
    belongs_to :blog_post, :counter_cache => true 
end 

ब्लॉग पोस्ट blog_comments_count नाम के एक स्तंभ के लिए होगा।

SELECT COUNT(*), blog_post_id 
    FROM blog_comments 
GROUP BY blog_post_id; 

आप इस का उपयोग टिप्पणियों की गिनती करने के लिए blog_post_id से एक हैश बनाने के लिए कर सकते हैं:

+0

+1 साफ है कि! –

+0

यह वही है जो मैं ढूंढ रहा था! धन्यवाद! – Mike

3

सामान्य तौर पर, यदि आप एक SQL क्वेरी की तरह चाहते हैं।

0

यह एक ActiveRecord क्वेरी है जो मेरी "site_access_log" तालिका को खोजती है, जिसमें वेब पर वेब पहुंच होती है।

यह पहले 15 रिकॉर्ड्स से 'रिमोट_एडआर' फ़ील्ड का चयन करता है, साथ ही उस आईपी के लिए गिनती के साथ, गिनती द्वारा अवरोही क्रम में क्रमबद्ध किया जाता है, जिसके बाद आईपी संख्याओं के लिए आरोही क्रम होता है, जिसमें समान count_number होता है।

मैं पोस्टग्रेस का उपयोग कर रहा हूं, जो आईपीवी 4 संख्याओं को समझता है, इसलिए मैंने फ़ील्ड को inet प्रकार पर डाला, ताकि ASCII मान के बजाय मूल्य द्वारा सही क्रमबद्ध करने की अनुमति दी जा सके। यदि आपका डेटाबेस इनसेट मानों का समर्थन नहीं करता है, तो आप रूबी की सॉकेट या आईपीएसकेट लाइब्रेरी का उपयोग करके आईपी से इनसेट में हमेशा कनवर्ट कर सकते हैं, फिर पुनर्प्राप्त परिणाम सॉर्ट करें।

@remote_addr_results = SiteAccessLog.all(
    :select  => 'remote_addr, count(remote_addr) as remote_addr_count', 
    :group  => :remote_addr, 
    :order  => 'remote_addr_count desc, cast(remote_addr as inet)', 
    :limit  => 15 
) 
puts @remote_addr_results.map{ |r| r.remote_addr_count << ' : ' << r.remote_addr } 

>> 985 : 68.228.61.183 
>> 572 : 205.203.134.197 
>> 500 : 68.32.220.153 
>> 460 : 72.200.64.128 
>> 281 : 24.121.196.194 
>> 262 : 99.91.9.155 
>> 241 : 68.99.237.178 
>> 213 : 68.99.119.137 
>> 208 : 70.167.157.162 
>> 204 : 201.165.6.2 
>> 164 : 72.201.233.147 
>> 155 : 75.245.177.106 
>> 150 : 97.123.246.154 
>> 149 : 201.165.190.98 
>> 145 : 74.37.165.220 

उत्पन्न एसक्यूएल लगता है:

BlogComment.group('blog_post_id').count 

विशुद्ध रूप से रेल मार्ग में:

SELECT remote_addr, count(remote_addr) as remote_addr_count                  
FROM "site_access_logs"                           
GROUP BY remote_addr                            
ORDER BY remote_addr_count desc, cast(remote_addr as inet)                   
LIMIT 15 
2

तुम भी कुछ इस तरह देख सकते हैं। :)

0

आप dase मणि या that video में वर्णित तकनीकों में से एक का उपयोग कर सकते हैं। Dase साथ

उदाहरण:

Author.includes_count_of(:articles).each do |author| puts "#{author.name} has #{author.articles_count} articles" end

संबंधित मुद्दे