For example if a User was checking in at Locations, that were being stored each time, we’d have something like this:
schema "users" do
has_many(:locations, MyApp.Schemas.Location)
end
What I would like to also add is something like:
has_one(:last_location, MyApp.Schemas.Location, ...some order by inserted_at/limit function...)
Is this possible? What’s the best way to do this?
Associations don’t support limit
directly, unfortunately.
You could use Ecto.Query.preload
with an appropriate query, but it will add complexity.
As an alternative, consider the way your application writes data. Is a Location
ever changed to a different User
, by updating user_id
? If it isn’t, then it would be safe to denormalize a little:
schema "users" do
has_many(:locations, MyApp.Schemas.Location)
belongs_to(:last_location, MyApp.Schemas.Location)
end
and then ensure that any time you add a new Location
record you also update the corresponding User
.
This approach is most valuable if the application mostly reads from last_location
, as it keeps the common queries as simple as possible.
The User ID doesn’t change, the table is just User_Ids and Postgis.Geom:
schema "locations" do
field(:geom, Geo.PostGIS.Geometry)
field(:user_id, :binary_id)
timestamps()
end
I’m a bit unclear on how that line you have:
belongs_to(:last_location, MyApp.Schemas.Location)
would work. For a given user they could have 0,1,…N Locations, so I’m unclear how just creating a belongs_to
entry would always pull the last one. Is there some other field I need to add?
Edit:
Oh, I see, I would be storing a last_location_id
on the user’s table?
Yup - the code that creates a new Location
would also ensure that the last_location_id
field on the user was updated.