Angenommen, Sie müssen den Benutzernamen der ersten fünf Beiträge abrufen. Du schreibst schnell die folgende Abfrage und genießt dein Wochenende.
posts = Post.limit(5)
posts.each do |post|
puts post.user.name
end
Gut. Aber schauen wir uns die Abfragen an
Post Load (0.5ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
1 query um alle posts abzurufen und 1 query um users abzurufen für jeden Beitrag ergibt sich insgesamt 6 queries . Schauen Sie sich die folgende Lösung an, die dasselbe tut, nur in 2 queries :
posts = Post.includes(:user).limit(5)
posts.each do |post|
puts post.user.name
end
#####
Post Load (0.3ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2)
Es gibt einen kleinen Unterschied. Fügen Sie includes(:posts) hinzu zu deiner Frage und Problem gelöst. Schnell, nett und einfach.
Aber fügen Sie nicht einfach includes hinzu in Ihrer Anfrage, ohne sie richtig zu verstehen. Die Verwendung von includes mit joins kann je nach Situation zu Cross-Joins führen, was in den meisten Fällen nicht erforderlich ist.
Wenn Sie Ihren eingeschlossenen Modellen Bedingungen hinzufügen möchten, müssen Sie explizit darauf verweisen . Zum Beispiel:
User.includes(:posts).where('posts.name = ?', 'example')
Wird einen Fehler auslösen, aber das wird funktionieren:
User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
Beachten Sie, dass includes funktioniert mit association names während references benötigt the actual table name .