2009-07-24 15 views
13

Desideroso di carico è bello con l'inclusione attribuiscoRails desiderosi di caricare i conteggi?

Post.find(:all, :include => :author) 

Mi chiedo se è possibile anche i conteggi di carico ansiosi, come se volevo ottenere il numero di commenti per ogni post, senza caricare tutti i commenti stessi?

Forse qualcosa di simile

Post.find(:all, :include => [:author, "count(comments)") 

Suppongo che potrei usare una colonna count_cache. Ma fare tutto questo in un contesto sarebbe davvero bello, se possibile.

Punti bonus extra se qualcuno può mostrare come ottenere non solo il conteggio, ma anche alcune condizioni, come il conteggio dei soli post che sono stati approvati.

+0

Questo è stato successivamente ampliato in questa domanda: http://stackoverflow.com/questions/4908878/how-do-i-get-rails-to-eager-load-counts Che è fortemente correlato a: http://stackoverflow.com/questions/2870521/how-will-activerelation-affect-rails-includes-s-capabilities (che è il modo in cui l'ho trovato) –

risposta

-6

Almeno in MySQL, è più veloce eseguire queste due chiamate separate perché si evita l'unione. So che questo non risponde alla tua domanda, ma sembra che si sta cercando di ottenere una migliore velocità e facendo

Post.find ... 

Poi

post.comments.count 

è più veloce e più efficiente della memoria (per il database) che se si recupera entrambi in una query.

+4

Bene, uno dei motivi principali per usare il caricamento bisognoso è evitare le query N + 1. – MrTheWalrus

+3

Ciò induce una query N + 1 e non risponde alla domanda. – davidgoli

24

dovrebbero già essere caricati uso

post.comments.length 

ho avuto questo stesso problema, perché stavo usando .count

+2

Non penso che questo sia ciò che sta cercando. Ciò caricherà tutte le voci nell'associazione di commenti e quindi li contatterà. Vuole usare SQL per tirare con entusiasmo il conteggio senza caricare gli oggetti. (O almeno è così che lo capisco). – Mike

+0

Hai ragione Mike. –

+1

Questa era la soluzione che stavo cercando. Attiva e indicizza la pagina dei post in cui desidero eseguire un'iterazione sulla raccolta e visualizzare il conteggio dei commenti, evitando così di attivare una richiesta di conteggio in ogni ciclo (a condizione che i commenti siano stati caricati insieme con i post). Grazie :-) – Renra

2

Prova questo:

Comment.count(:group => :post) 

Per filtrare da condizioni:

Comment.count(:group => :post, :conditions => {:approved => true }) 

Questi restituiranno gli hash con i messaggi come chiavi e il numero di commenti come valori.

+0

Non è esattamente quello che sto cercando. Sì, puoi farlo in una chiamata separata come questa. Ma non penso che tu possa farli in un'associazione come volevo. Probabilmente dovresti usare la colonna count_cache. –

3

Compilando la risposta di avaynshtok, la seguente tecnica dovrebbe effettuare solo 2 chiamate al database.

# ./app/controllers/posts_controller.rb 

def index 
    # First load the posts 
    @posts = Post.all 

    # Then you can load a hash of author counts grouped by post_id 
    # Rails 3 version: 
    @comment_counts = Comment.count(:group => :post_id) 
    # Rails 4 version: 
    # @comment_counts = Comment.group(:post_id).count 
end 

Quindi secondo lei

<!-- ./app/views/posts/index.html.erb --> 

<% @posts.each do |post| %> 
    <!-- reference the count by the post.id --> 
    post_count: <%= @comment_counts[post.id] %> 
<% end %> 
0

Ho appena incontrato questa sfida e risolto in questo modo:

def trainee_counts 
    @trainee_counts ||= Hash[Trainee.group(:klass_id).count] 
end 

    # where the count is needed 
    trainee_counts[klass_id].to_i 

Una chiamata al database e non caricare tirocinanti.

Problemi correlati