Reputation:
c = Conversation.joins(:messages).random
>> Conversation Load (8.1ms) SELECT `conversations`.* FROM `conversations` INNER JOIN `messages` ON `messages`.`conversation_id` = `conversations`.`id` ORDER BY created_at DESC, RAND() LIMIT 1
Count:
c.messages.count
>> (5.7ms) SELECT COUNT(*) FROM `messages` WHERE `messages`.`conversation_id` = 74
Length:
c.messages.length
>> Message Load (1.2ms) SELECT `messages`.* FROM `messages` WHERE `messages`.`conversation_id` = 82
How to not perform additional queries above? I thought I have already joined messages for the random conversation using INNER JOIN, and yet a new query is performed to count those results?
The second issue is attempting to get all joined messages with a specific user_id:
u = User with id 27 # has messages in 'c' results above
c.messages.where('user_id = ?', u.id).all
>> Message Load (5.3ms) SELECT `messages`.* FROM `messages` WHERE `messages`.`conversation_id` = 82 AND (user_id = 27)
I used select to do this without additional queries:
c.messages.select { |msg| msg.user_id == u.id }
>> returns messages without query logged
I'd still appreciate how I might reduce or optimize these queries.
Upvotes: 1
Views: 651
Reputation: 15109
Try using includes
instead of joins
to avoid the n+1 problem.
Railscast #181 By Ryan Bates, http://railscasts.com/episodes/181-include-vs-joins?view=asciicast, explains the difference in an easy way.
Upvotes: 1