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
.