W przypadku Firebase Data Connect projektujesz schemat GraphQL, który reprezentuje model danych wymagany przez Twoją aplikację. Data Connect przekształca ten schemat w instancję Cloud SQL for PostgreSQL, która obsługuje Twoją aplikację. Następnie tworzysz zapytania i mutacje, aby komunikować się z backendem, i łączysz te operacje w konektory, aby używać danych z kodu klienta.
Data Connect udostępnia narzędzia AI, które pomagają projektować i wdrażać schematy. W tym przewodniku przedstawiamy ważne koncepcje projektowania schematów, które pomogą Ci w standardowych i wspomaganych przez AI przepływach pracy podczas tworzenia aplikacji i po jego zakończeniu.
W przewodniku dla początkujących przedstawiliśmy schemat aplikacji do oceniania filmów w PostgreSQL.
W tym przewodniku rozwijamy ten schemat i podajemy listę SQL odpowiadającą ostatecznemu schematowi aplikacji do recenzowania filmów.
Schemat aplikacji do recenzowania filmów
Załóżmy, że chcesz utworzyć usługę, która umożliwia użytkownikom przesyłanie i wyświetlanie recenzji filmów.
Aby obsługiwać podstawowe zapytania, musisz mieć początkowy schemat takiej aplikacji. Ten schemat możesz później rozszerzyć, aby tworzyć złożone zapytania relacyjne.
W Data Connect zdefiniujesz typy GraphQL, aby określić kształt danych, o które klienci mogą wysyłać zapytania i którymi mogą manipulować. Podczas pisania schematu typy są tłumaczone na tabele Cloud SQL for PostgreSQL, najczęściej w bezpośredniej relacji między typami GraphQL a tabelami bazy danych, chociaż możliwe są też inne mapowania. W tym przewodniku znajdziesz przykłady od podstawowych po bardziej zaawansowane.
Zdefiniuj podstawowy typ Movie
Możesz zacząć od typu Movie
.
Schemat pliku Movie
zawiera podstawowe dyrektywy, takie jak:
@table(name)
i@col(name)
, aby dostosować nazwy tabel i kolumn SQL. Jeśli nie podasz nazwy, Data Connect wygeneruje nazwy w formacie snake_case.@col(dataType)
, aby dostosować typy kolumn SQL.@default
, aby skonfigurować domyślne wartości kolumn SQL podczas wstawiania.
Więcej informacji znajdziesz w dokumentacji referencyjnej dotyczącej @table
, @col
i @default
.
# Movies
type Movie @table(name: "movie", key: "id") {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int
genre: String @col(dataType: "varchar(20)")
rating: Int
description: String
}
Automatyczne przechowywanie ważnych danych użytkowników w User
Aplikacja będzie śledzić użytkowników, więc potrzebujesz typu User
.
W tym przypadku szczególnie przydatna jest dyrektywa @default
. Pole id
może automatycznie pobierać identyfikator użytkownika z uwierzytelniania. Zwróć uwagę na użycie @default(expr: "auth.uid")
w tym przykładzie.
# Users
# Suppose a user can leave reviews for movies
type User @table {
id: String! @default(expr: "auth.uid")
username: String! @col(dataType: "varchar(50)")
}
Kluczowe wartości skalarne i wartości serwera
Zanim przyjrzymy się bliżej aplikacji do oceniania filmów, warto zapoznać się z Data Connect kluczowymi skalarami i wartościami serwera.
Kluczowe skalary to zwięzłe identyfikatory obiektów, które Data Connect automatycznie tworzy na podstawie kluczowych pól w Twoich schematach. Kluczowe skalary dotyczą wydajności, ponieważ umożliwiają uzyskanie w ramach jednego wywołania informacji o tożsamości i strukturze danych. Są one szczególnie przydatne, gdy chcesz wykonywać sekwencyjne działania na nowych rekordach i potrzebujesz unikalnego identyfikatora do przekazywania do kolejnych operacji, a także gdy chcesz uzyskać dostęp do kluczy relacyjnych, aby wykonywać dodatkowe, bardziej złożone operacje.
Korzystając z wartości serwera, możesz skutecznie zezwolić serwerowi na dynamiczne wypełnianie pól w tabelach za pomocą przechowywanych lub łatwo obliczalnych wartości zgodnie z określonymi wyrażeniami CEL po stronie serwera w argumencie expr
. Możesz na przykład zdefiniować pole z sygnaturą czasową, która jest stosowana, gdy uzyskuje się do niego dostęp przy użyciu czasu przechowywanego w żądaniu operacji, updatedAt: Timestamp!
@default(expr: "request.time")
.
Obsługa relacji „wiele do wielu” w przypadku typów Actor
i MovieActor
Po obsłużeniu użytkowników możesz wrócić do modelowania danych o filmach.
Następnie chcesz, aby w Twoich filmach występowali aktorzy.
Tabela Actor
jest dość prosta.
# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table {
id: UUID! @default(expr: "uuidV4()")
name: String! @col(dataType: "varchar(30)")
}
Jeśli chcesz, aby aktorzy występowali w wielu filmach, a filmy miały wielu aktorów, musisz utworzyć „tabelę złączeń”.
Tabela MovieActor
obsługuje relację wiele do wielu, a jej klucz podstawowy to kombinacja [movie, actor]
(pola klucza obcego z tabel movie
i actor
).
# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary keys of this table
# In this case, the keys are [movieId, actorId], the foreign key fields of the reference fields [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
movie: Movie!
# movieId: UUID! <- implicitly added foreign key field
actor: Actor!
# actorId: UUID! <- implicitly added foreign key field
role: String! # "main" or "supporting"
# optional other fields
}
Gdy zdefiniujesz relację SQL w tabeli z ograniczeniem klucza obcego, Data Connect automatycznie wygeneruje odpowiednie pole po drugiej stronie. Nie musisz definiować pola mapowania odwrotnego (np. z Actor
z powrotem do MovieActor
).
Obsługa relacji jeden do jednego w typie MovieMetadata
Teraz możesz śledzić reżyserów filmowych i skonfigurować relację jeden do jednego z Movie
.
Aby dostosować ograniczenia klucza obcego, możesz użyć dyrektywy @ref
:
@ref(fields)
określa, których pól klucza obcego użyć.@ref(references)
określa pola, do których odwołuje się tabela docelowa (domyślnie jest to klucz podstawowy, ale działają też pola@unique
). Jest to bardziej zaawansowana opcja. Data Connect często może to zrobić za Ciebie.
Więcej informacji znajdziesz w dokumentacji referencyjnej dotyczącej @ref
.
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
# @unique ensures that each Movie only has one MovieMetadata.
movie: Movie! @unique
# Since it references to another table type, it adds a foreign key constraint.
# movie: Movie! @unique @ref(fields: "movieId", references: "id")
# movieId: UUID! <- implicitly added foreign key field
director: String
}
Używaj pól wygenerowanych na podstawie schematu do tworzenia operacji
Operacje Data Connect rozszerzą zestaw pól automatycznie wygenerowanych Data Connect na podstawie typów i relacji między typami w schemacie. Pola te są generowane przez narzędzia lokalne za każdym razem, gdy edytujesz schemat.
Załóżmy, że schemat zawiera typ Movie
i powiązany z nim typ Actor
.
Data Connect generuje pola movie
, movies
, actors_on_movies
i inne.
Zapytanie z polem
movie
Pole |
Użyj tego pola, aby wysłać zapytanie o jeden film na podstawie jego klucza. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Zapytanie z polem
movies
Pole |
Użyj tego pola, aby wysłać zapytanie dotyczące wielu filmów, np. wszystkich filmów z danego roku. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Zapytanie z polem
actors_on_movies
Pole |
Użyj tego pola, aby wysłać zapytanie o wszystkich aktorów powiązanych z danym filmem. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
W przewodniku po implementacji zapytań i przewodniku po implementacji mutacji znajdziesz informacje o tym, jak implementować operacje za pomocą tych pól.
Bardziej zaawansowane koncepcje schematu
Pola wyliczeniowe
Data Connect obsługuje pola wyliczeniowe, które są mapowane na typy wyliczeniowe PostgreSQL. Wyliczenia umożliwiają szybkie zdefiniowanie listy statycznych, wstępnie zdefiniowanych wartości w określonej kolejności.
Aby dodać wyliczenie do schematu, zadeklaruj je i jego wstępnie zdefiniowane wartości, a następnie odwołaj się do niego w typie.
enum AspectRatio {
ACADEMY
WIDESCREEN
ANAMORPHIC
IMAX
"No information available on aspect ratio"
UNAVAILABLE
}
type Movie
@table {
title: String!
genre: String
description: String
originalAspectRatio: AspectRatio! @default(value: WIDESCREEN)
otherAspectRatios: [AspectRatio!]
tags: [String]
rating: Float
imageUrl: String!
releaseYear: Int
}
W typie Movie
dodaliśmy pole wyliczeniowe originalAspectRatio
dla formatu obrazu, w którym film został nakręcony, oraz inne pole otherAspectRatios
dla listy innych dostępnych formatów obrazu.
Zarządzanie zmianami w polach wyliczeniowych
Możesz dodawać nowe wartości do wyliczenia, ale kolejność listy wyliczeń ma duże znaczenie, więc dodawaj nowe wartości z rozwagą. Jedyną w pełni wstecznie zgodną zmianą w wyliczeniu jest dodanie nowej wartości na końcu listy wartości. Wstawienie nowej wartości między wcześniej opublikowanymi wyliczeniami lub zmiana kolejności istniejących wartości zmienia kolejność względną, gdy w zapytaniach używane są operatory względne, takie jak „mniejsze niż”. Usuwanie lub zmienianie nazw wartości jest zawsze zmianą powodującą brak zgodności wstecznej.
Nigdy nie zmieniaj kolejności wartości na liście wartości wyliczeniowych, ponieważ ma to wpływ na sposób stosowania filtrowania.
Zmiany wartości wyliczeniowych należy wprowadzać ostrożnie, aby nie uszkodzić starszych wersji operacji ani kodu klienta. Podczas usuwania lub zmieniania nazwy wartości wyliczenia upewnij się, że w bieżącej bazie danych nie ma już żadnych instancji.
Używanie pól wyliczeniowych w operacjach i kodzie klienta
Po dodaniu do schematu pola wyliczeniowego możesz używać tego pola w zapytaniach i kodzie klienta.
Więcej informacji o tworzeniu zapytań z użyciem wyliczeń i o tym, jak pisać zapytania klienta, aby zezwalać na dostosowywanie wyliczeń, znajdziesz w przewodniku po zapytaniach.
Inne zaawansowane koncepcje
Aby wyjść poza podstawowe, ale przydatne typy i relacje, zapoznaj się z przykładami w dokumentacji.
Obsługiwane typy danych
Data Connect obsługuje te skalarne typy danych, które są przypisane do typów PostgreSQL za pomocą @col(dataType:)
.
Data Connect type | Wbudowany typ GraphQL lub Data Connect typ niestandardowy |
Domyślny typ PostgreSQL | Obsługiwane typy PostgreSQL (alias w nawiasach) |
---|---|---|---|
Ciąg znaków | GraphQL | tekst | text bit(n), varbit(n) char(n), varchar(n) |
Liczba całkowita | GraphQL | int | Int2 (smallint, smallserial), int4 (integer, int, serial) |
Liczba zmiennoprzecinkowa | GraphQL | float8 | float4 (real) float8 (double precision) numeric (decimal) |
Wartość logiczna | GraphQL | Wartość logiczna | Wartość logiczna |
UUID | Niestandardowy | uuid | uuid |
Int64 | Niestandardowy | bigint | int8 (bigint, bigserial) numeric (decimal) |
Data | Niestandardowy | date | data |
Sygnatura czasowa | Niestandardowy | timestamptz | timestamptz Uwaga: informacje o lokalnej strefie czasowej nie są przechowywane. |
Wyliczenie | Niestandardowy | enum | enum | typ wyliczeniowy |
Wektor | Niestandardowy | vector | wektor Zobacz Przeprowadzanie wyszukiwania podobieństwa wektorowego za pomocą Vertex AI. |
- GraphQL
List
jest mapowany na tablicę jednowymiarową.- Na przykład
[Int]
jest mapowany naint5[]
, a[Any]
najsonb[]
. - Data Connect nie obsługuje zagnieżdżonych tablic.
- Na przykład
Odpowiednik w schemacie SQL
-- Movies Table
CREATE TABLE Movies (
movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
title VARCHAR(255) NOT NULL,
release_year INT,
genre VARCHAR(30),
rating INT,
description TEXT,
tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
director VARCHAR(255) NOT NULL,
PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
movie_id UUID REFERENCES Movies(movie_id),
actor_id UUID REFERENCES Actors(actor_id),
role VARCHAR(50) NOT NULL, # "main" or "supporting"
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_auth VARCHAR(255) NOT NULL
username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES Users(user_id),
movie_id UUID REFERENCES Movies(movie_id),
rating INT,
review_text TEXT,
review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (movie_id, user_id)
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);
Dalsze kroki
Może Cię zainteresować:
- Generowanie schematów aplikacji za pomocą narzędzi wspomaganych przez AI
- Zapoznaj się z dokumentacją składni.