As a follow-on to this conversation, I have a solution using a calculation, but it introduces an N+1 query.
And now I’m working on a very similar part of the application, on basically the same problem. This time, I want to avoid the N+1 query.
In a conversation forum, there are Conversations, Users, and Messages. In my system, there is a join resource we’ll call ConversationUser, that relates a User with a Conversation. It also tracks the most recent Message the User has seen, stored as last_read_message_id. There is a listConversations
AshGraphql query, and it now needs to include a count of the number of unread messages in the result. The path to that count would be conversations.selfConversationUser.unreadMessagesCount
.
As before, I successfully implemented this as a calculation. And again, it introduces an N+1 query, because it loads from the database for each Conversation. So I’m going back to my first post, and looking for a solution using an aggregate. I made some headway, but I can’t figure out how to do the complex joining that needs to happen.
This is how far I’ve gone:
defmodule ConversationUser do
aggregates do
count :unread_messages_count, [:conversation, :messages] do
join_filter [:conversation, :messages], expr(id == parent(parent(last_read_message_id)))
end
end
The above successfully calculates 1
if there is a last_read_message_id
, but it needs to do much better: it needs to count the number of messages that were created after that particular message. So it needs another join on messages, where inserted_at is greater than the initial joined message. Is that possible? Or do you have a better approach?