Hi,
I have been breaking my head over the following query for the past day.
I have a Games table, and GameEvents table. In the games table game information is stored and in the game_events table, events regarding the games are stored (per user). I want to get a list of 9 recent games per user.
I thought ‘oh easy’, select all game_events where device_uuid (user) matches passed in device_uuid, distinct on game_id and sort by inserted_at. Alas this isn’t the case when using distinct with a sort_by on another column. I did some more searching and found a couple of nice examples and managed to create the sql query that gets the work done:
schema structure:
schema "games" do
has_many :game_events, GameEvent, on_delete: :delete_all
... omitted fields...
timestamps()
end
schema "game_events" do
belongs_to :game, Game
field :external_user_token, :string
field :device_uuid, :string
field :type, :string
field :payload, :map
timestamps()
end
Query that gives the desired result:
SELECT ges.game_id, ges.inserted_at, ges.device_uuid FROM game_events ges
JOIN (
SELECT game_id, max(inserted_at) max_inserted_at
FROM game_events
WHERE device_uuid = '1234'
GROUP BY game_id
) recent_ges
ON ges.game_id = recent_ges.game_id AND ges.inserted_at = recent_ges.max_inserted_at
ORDER BY ges.inserted_at DESC
LIMIT 9
My querstion now is, how do I get this query into ecto. I’ve managed to get the sub_query in the join working:
# The dynamic is used to select on the device_uuid (or external_user_token).
def game_events_preload(%{attribute: attribute, value: value}) do
from ge in __MODULE__,
where: ^dynamic([ge], field(ge, ^attribute) == ^value)
end
subquery =
external_user_identifier
|> game_events_preload()
|> select([ge], %{game_id: ge.game_id, max_inserted_at: max(ge.inserted_at)}) # I dont know if this map can work like an alias (recent_ges)
|> group_by([ge], ge.game_id)
# How do I get this join with the irder rught?
game_ids =
from ge in __MODULE__,
join: unique_ges in ^subquery
But I can’t seem to get the subquery JOIN with the ON and ORDER BY working. Is this possible in ecto? Or is there another way to achieve the desired result?
Thanks!