Simplify data model

Artists can be embedded inside records - given the projected size of the
dataset (a few 1000s in the worst case) relationships can be built in
memory without the need to be denormalized into separate tables.
This commit is contained in:
Claudio Ortolina
2024-09-15 19:32:50 +01:00
parent 988d311fef
commit affa7a007e
5 changed files with 23 additions and 57 deletions
+1 -9
View File
@@ -37,15 +37,7 @@ defmodule MusicLibrary.Records do
** (Ecto.NoResultsError)
"""
def get_record!(id) do
q =
from r in Record,
left_join: a in assoc(r, :artists),
preload: [artists: a],
where: r.id == ^id
Repo.one!(q)
end
def get_record!(id), do: Repo.get!(Record, id)
@doc """
Creates a record.
-25
View File
@@ -1,25 +0,0 @@
defmodule MusicLibrary.Records.Artist do
use Ecto.Schema
import Ecto.Changeset
alias MusicLibrary.{Records.ArtistRecord, Records.Record}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "artists" do
field :name, :string
field :image, :string
field :musicbrainz_id, Ecto.UUID
many_to_many :records, Record, join_through: ArtistRecord
timestamps(type: :utc_datetime)
end
@doc false
def changeset(artist, attrs) do
artist
|> cast(attrs, [:name, :musicbrainz_id, :image])
|> validate_required([:name, :musicbrainz_id, :image])
end
end
@@ -1,20 +0,0 @@
defmodule MusicLibrary.Records.ArtistRecord do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "artists_records" do
field :artist_id, :binary_id
field :record_id, :binary_id
timestamps(type: :utc_datetime)
end
@doc false
def changeset(artist_record, attrs) do
artist_record
|> cast(attrs, [])
|> validate_required([])
end
end
+10 -3
View File
@@ -2,8 +2,6 @@ defmodule MusicLibrary.Records.Record do
use Ecto.Schema
import Ecto.Changeset
alias MusicLibrary.{Records.Artist, Records.ArtistRecord}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "records" do
@@ -14,7 +12,10 @@ defmodule MusicLibrary.Records.Record do
field :musicbrainz_id, Ecto.UUID
field :genres, {:array, :string}
many_to_many :artists, Artist, join_through: ArtistRecord
embeds_many :artists, Artist do
field :name, :string
field :musicbrainz_id, Ecto.UUID
end
timestamps(type: :utc_datetime)
end
@@ -25,4 +26,10 @@ defmodule MusicLibrary.Records.Record do
|> cast(attrs, [:type, :title, :musicbrainz_id, :year, :genres, :image])
|> validate_required([:type, :title, :musicbrainz_id, :year, :genres, :image])
end
def add_artists(record, artists_attrs) do
record
|> change()
|> put_embed(:artists, artists_attrs)
end
end
@@ -0,0 +1,12 @@
defmodule MusicLibrary.Repo.Migrations.EmbedArtists do
use Ecto.Migration
def change do
drop table(:artists_records)
drop table(:artists)
alter table(:records) do
add :artists, :map
end
end
end