Assosiasjoner og innebygde skjemaer
Håndter relasjoner mellom ulike datamodeller ved hjelp av Ecto-assosiasjoner, og bygg inn data direkte med innebygde skjemaer.
Assosiasjoner og innebygde skjemaer er en gratis leksjon i Elixir og Phoenix: Skalerbar backendutvikling på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Elixir og Phoenix: Skalerbar backendutvikling, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Elixir og Phoenix: Skalerbar backendutvikling inneholder totalt 4 leksjoner.
Knytte dataene sammen
I relasjonsdatabaser er data ofte fordelt på flere tabeller for å unngå redundans og sikre dataintegritet. Assosiasjoner i Ecto hjelper Dem med å definere hvordan disse ulike delene av data henger sammen.
Tenk på en blogg: En bruker kan skrive mange innlegg, og hvert innlegg tilhører én bruker. Ecto lar Dem modellere disse relasjonene direkte i Elixir-skjemaene.
- Organiserer relaterte data på en logisk måte.
- Forenkler spørringer og uthenting av data.
- Opprettholder datakonsistens.
Én bruker, mange innlegg
Den vanligste relasjonen er én-til-mange. For eksempel kan én User ha mange Post-poster, men hver Post tilhører bare én User.
I Ecto definerer De dette ved å bruke has_many på «én»-siden (for eksempel User) og belongs_to på «mange»-siden (for eksempel Post). Makroen belongs_to forteller også Ecto at det skal legges til en fremmednøkkel (for eksempel user_id) i databasetabellen til Post.
Kode med `has_many` og `belongs_to`
La oss definere User- og Post-skjemaene. Legg merke til hvordan has_many og belongs_to knytter dem sammen. Makroen belongs_to forventer navnet på assosiasjonen og modulen til det tilknyttede skjemaet.
defmodule MyApp.User do
use Ecto.Schema
schema "users" do
field :name, :string
has_many :posts, MyApp.Post # A user has many posts
timestamps()
end
end
defmodule MyApp.Post do
use Ecto.Schema
schema "posts" do
field :title, :string
field :content, :string
belongs_to :user, MyApp.User # A post belongs to one user
timestamps()
end
endArbeide med koblede poster
Når skjemaene er definert, kan De opprette poster og knytte dem sammen. Ecto lar Dem forhåndslaste assosiasjoner ved å hente relaterte data i én enkelt spørring, slik at N+1-problemer unngås. Slik kan De opprette en bruker og innlegg og deretter vise brukeren med innleggene sine.
defmodule MyScript do
# Mock schemas for demonstration (assuming they are defined)
defmodule User do
defstruct [:id, :name, :posts]
end
defmodule Post do
defstruct [:id, :title, :content, :user_id]
end
def run do
IO.puts "--- Demonstrating One-to-Many ---"
# Simulate creating a user
user = %User{id: 1, name: "Alice"}
IO.inspect user, label: "Created User"
# Simulate creating posts linked to the user
post1 = %Post{id: 101, title: "My First Post", content: "Hello world!", user_id: user.id}
post2 = %Post{id: 102, title: "Elixir Fun", content: "Learning Elixir!", user_id: user.id}
# In a real app, you'd use Repo.insert! and Repo.preload
# To show the concept of preloading, we manually add posts to the user struct
user_with_posts = %{user | posts: [post1, post2]}
IO.inspect user_with_posts, label: "User with preloaded posts"
end
end
MyScript.run()Flere koblinger: `many_to_many`
Noen ganger har poster en mange-til-mange-relasjon. For eksempel kan en Student melde seg på mange Course-kurs, og hvert Course kan ha mange Student-studenter.
Ecto håndterer dette ved hjelp av en koblingstabell (eller «pivot-tabell»). De definerer et skjema for denne mellomliggende tabellen, og Ecto bruker det til å administrere koblingene mellom de to hovedskjemaene med makroen many_to_many.
- Krever et separat koblingsskjema.
- Knytter sammen to skjemaer der begge sider kan ha flere relaterte poster.
- Vanlig for tagger, roller eller gruppemedlemskap.
Kode med `many_to_many`
La oss definere Student- og Course-skjemaene sammen med et Enrollment-koblingsskjema. Makroen many_to_many brukes på både Student og Course, og koblingsskjemaet angis.
defmodule MyApp.Student do
use Ecto.Schema
schema "students" do
field :name, :string
many_to_many :courses, MyApp.Course, join_through: MyApp.Enrollment
timestamps()
end
end
defmodule MyApp.Course do
use Ecto.Schema
schema "courses" do
field :title, :string
many_to_many :students, MyApp.Student, join_through: MyApp.Enrollment
timestamps()
end
end
defmodule MyApp.Enrollment do
use Ecto.Schema
schema "enrollments" do
# These are foreign keys to Student and Course
belongs_to :student, MyApp.Student
belongs_to :course, MyApp.Course
timestamps()
end
endFå tilgang til mange-til-mange-koblinger
På samme måte som ved én-til-mange bruker De Ecto.Repo.preload/2 til å hente tilknyttede mange-til-mange-poster. Ecto håndterer automatisk spørringen mot koblingstabellen i bakgrunnen.
defmodule MyScript.Many do
# Mock schemas for demonstration
defmodule Student do
defstruct [:id, :name, :courses]
end
defmodule Course do
defstruct [:id, :title, :students]
end
defmodule Enrollment do
defstruct [:id, :student_id, :course_id]
end
def run do
IO.puts "--- Demonstrating Many-to-Many ---"
# Simulate creating a student and courses
student1 = %Student{id: 1, name: "Maria"}
courseA = %Course{id: 101, title: "Elixir Basics"}
courseB = %Course{id: 102, title: "Phoenix Framework"}
# Simulate enrollments (join table entries)
_enrollment1 = %Enrollment{student_id: student1.id, course_id: courseA.id}
_enrollment2 = %Enrollment{student_id: student1.id, course_id: courseB.id}
# Simulate preloading courses for student1
student1_with_courses = %{student1 | courses: [courseA, courseB]}
IO.inspect student1_with_courses, label: "Student with preloaded courses"
end
end
MyScript.Many.run()Data i data: Innebygde skjemaer
Mens assosiasjoner kobler sammen separate poster, lar innebygde skjemaer deg lagre strukturerte data direkte i et felt i en overordnet post. Det betyr at de innebygde dataene ikke ligger i en separat tabell, men er en del av raden til den overordnede posten.
Bruk innebygde skjemaer når de nøstede dataene bare gir mening i sammenheng med den overordnede posten, og ikke trenger å spørres etter eller deles separat.
- Data lagres direkte i den overordnede posten.
- Ingen separat databasetabell eller fremmednøkler.
- Ideelt for enkle, avhengige nøstede data som adresser eller metadata.
Koding av innebygde skjemaer
Du definerer et innebygd skjema ved å bruke embeds_one eller embeds_many i det overordnede skjemaet. Selve det innebygde skjemaet bruker Ecto.Schema sammen med @primary_key false og @foreign_key_type :binary_id (eller false hvis det ikke skal ha noen ID), siden det ikke er en frittstående tabell.
defmodule MyScript.Embed do
defmodule Address do
use Ecto.Schema
@primary_key false # Embedded schemas don't have their own primary key
@foreign_key_type :binary_id # Or false if no ID needed at all
schema "addresses" do # Table name is ignored for embeds
field :street, :string
field :city, :string
field :zip_code, :string
end
end
defmodule Profile do
use Ecto.Schema
schema "profiles" do
field :username, :string
embeds_one :address, MyScript.Embed.Address, on_replace: :delete # Embeds one address
timestamps()
end
end
def run do
IO.puts "--- Demonstrating Embedded Schemas ---"
# Create a profile with an embedded address
profile_changeset =
Ecto.Changeset.change(%Profile{}, %{username: "john_doe"})
|> Ecto.Changeset.put_embed(:address, %{
street: "123 Main St",
city: "Anytown",
zip_code: "12345"
})
# In a real app: Repo.insert!(profile_changeset)
# Simulate the resulting struct
profile_with_address = %Profile{
id: 1,
username: "john_doe",
address: %Address{street: "123 Main St", city: "Anytown", zip_code: "12345"}
}
IO.inspect profile_with_address, label: "Profile with embedded address"
end
end
MyScript.Embed.run()Test forståelsen
Du har lært om Ecto-assosiasjoner og innebygde skjemaer. La oss teste kunnskapene dine!
Assosiasjoner og innebygde skjemaer: Viktige punkter
Godt jobbet! Du har fått kontroll på hvordan relasjoner modelleres i Ecto:
- En-til-mange: Bruk
has_manyogbelongs_to. Fremmednøkkelen ligger påbelongs_to-siden. - Mange-til-mange: Bruk
many_to_manysammen med et egetjoin_through-skjema. - Innebygde skjemaer: Bruk
embeds_oneellerembeds_manytil å lagre avhengige, strukturerte data direkte i en overordnet post. - Bruk alltid
Ecto.Repo.preload/2for å hente tilknyttede data effektivt.
Disse kraftige funksjonene er grunnleggende for å bygge robuste og velstrukturerte Ecto-applikasjoner. Fortsett å øve!
Lær deg Elixir med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 12
- Leksjoner
- 48
Ofte stilte spørsmål
Er leksjonen «Assosiasjoner og innebygde skjemaer» gratis?
Ja – hele teksten i «Assosiasjoner og innebygde skjemaer» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Elixir og Phoenix: Skalerbar backendutvikling-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Elixir og Phoenix: Skalerbar backendutvikling inneholder totalt 4 leksjoner.
Hva lærer jeg i «Assosiasjoner og innebygde skjemaer»?
Håndter relasjoner mellom ulike datamodeller ved hjelp av Ecto-assosiasjoner, og bygg inn data direkte med innebygde skjemaer. Du øver på Elixir og Phoenix: Skalerbar backendutvikling med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Elixir og Phoenix: Skalerbar backendutvikling?
Ingen tidligere erfaring er nødvendig. Elixir og Phoenix: Skalerbar backendutvikling på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Assosiasjoner og innebygde skjemaer»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Elixir og Phoenix: Skalerbar backendutvikling-leksjonen?
Ja. Alle Elixir og Phoenix: Skalerbar backendutvikling-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Ecto-skjemaer og databasemigreringer
- Repo, Changesets og spørringer
- Assosiasjoner og innebygde skjemaer
- Transaksjoner og Ecto.Multi