W Firebase SQL Connect projektujesz schemat GraphQL, który reprezentuje model danych wymagany przez aplikację. SQL Connect konwertuje ten schemat na instancję Cloud SQL for PostgreSQL, która obsługuje Twoją aplikację. Następnie tworzysz zapytania i mutacje, aby połączyć się z backendem, i łączysz te operacje w oprogramowanie sprzęgające, aby używać danych z kodu klienta.
SQL Connect oferuje narzędzia AI, które pomagają w projektowaniu i wdrażaniu schematów. W tym przewodniku przedstawiamy ważne pojęcia związane z projektowaniem schematów, które pomogą Ci w standardowych i wspomaganych przez AI przepływach pracy, gdy zaczniesz tworzyć aplikację i później.
W przewodniku dla początkujących przedstawiliśmy schemat aplikacji do recenzowania 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
Wyobraź sobie, że chcesz utworzyć usługę, która umożliwia użytkownikom przesyłanie i wyświetlanie recenzji filmów.
Aby taka aplikacja mogła obsługiwać podstawowe zapytania, potrzebny jest schemat początkowy. Później rozszerzysz ten schemat, aby tworzyć złożone zapytania relacyjne.
W pliku SQL Connect zdefiniujesz typy GraphQL, aby określić kształt danych, które klienci mogą wyszukiwać i modyfikować. Gdy piszesz schemat, typy są tłumaczone na tabele Cloud SQL dla 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 kilka przykładów, od podstawowych po bardziej zaawansowane.
Zdefiniuj podstawowy typ Movie
Możesz zacząć od typu Movie.
Schemat Movie zawiera podstawowe dyrektywy, takie jak:
@table(name)i@col(name), aby dostosować nazwy tabel i kolumn SQL. Jeśli nie zostanie określony, SQL 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, @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
}
Automatycznie przechowuj ważne dane użytkownika w typie User
Twoja 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 poniższym 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 skalary i wartości serwera
Zanim przyjrzymy się bliżej aplikacji do recenzowania filmów, warto przedstawić SQL Connect kluczowe skalary i wartości serwera.
Skalary kluczy to zwięzłe identyfikatory obiektów, które SQL Connect automatycznie tworzy z pól kluczy w schematach. Kluczowe skalary dotyczą wydajności, umożliwiając znalezienie informacji o tożsamości i strukturze danych w jednym wywołaniu. Są szczególnie przydatne, gdy chcesz wykonywać sekwencyjne działania na nowych rekordach i potrzebujesz unikalnego identyfikatora, który możesz przekazać do kolejnych operacji, a także gdy chcesz uzyskać dostęp do kluczy relacyjnych, aby wykonywać dodatkowe, bardziej złożone operacje.
Za pomocą wartości serwera możesz skutecznie umożliwić serwerowi dynamiczne wypełnianie pól w tabelach przy użyciu przechowywanych lub łatwych do obliczenia 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 pole jest używane, przy użyciu czasu zapisanego w żądaniu operacji updatedAt: Timestamp!
@default(expr: "request.time").
Obsługa relacji wiele do wielu w typach Actor i MovieActor
Po obsłużeniu użytkowników możesz wrócić do modelowania danych filmów.
Teraz potrzebujesz aktorów, którzy zagrają w Twoich filmach.
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, potrzebujesz „tabeli połączeń”.
Tabela MovieActor obsługuje relację wiele do wielu, a jej klucz podstawowy jest kombinacją [movie, actor] (pól klucza obcego z 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, SQL 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 filmów i skonfigurować relację jeden do jednego z tabelą Movie.
Aby dostosować ograniczenia klucza obcego, możesz użyć dyrektywy @ref:
@ref(fields)określa, których pól klucza obcego należy użyć.@ref(references)określa pola, do których odwołuje się tabela docelowa (domyślnie jest to klucz podstawowy, ale pola@uniqueteż działają). Jest to bardziej zaawansowana opcja. SQL Connect często może to wywnioskować za Ciebie.
Więcej informacji znajdziesz w dokumentacji referencyjnej @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żywanie pól wygenerowanych na podstawie schematu do tworzenia operacji
Operacje SQL Connect rozszerzą zestaw pól generowanych automatycznie przez SQL Connect na podstawie typów i relacji typów w schemacie. Te pola są generowane przez narzędzia lokalne za każdym razem, gdy edytujesz schemat.
Załóżmy, że schemat zawiera typ Movie i powiązany typ Actor.
SQL Connect generuje pola movie, movies, actors_on_movies i inne.
Zapytanie z polem
movie
|
Pole |
Użyj tego pola, aby wyszukać pojedynczy film według jego klucza. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Zapytanie z polem
movies
|
Pole |
Użyj tego pola, aby wysłać zapytanie o wiele filmów, na przykład o wszystkie filmy 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 } } } |
Mając to na uwadze, możesz przeczytać, jak implementować operacje za pomocą tych pól, w przewodniku po implementacji zapytań i przewodniku po implementacji mutacji.
Bardziej zaawansowane koncepcje schematów
Pola wyliczenia
SQL Connect obsługuje pola wyliczeniowe, które są mapowane na typy wyliczeniowe PostgreSQL. Typy wyliczeniowe umożliwiają szybkie definiowanie listy statycznych, wstępnie zdefiniowanych wartości w określonej kolejności.
Aby dodać typ wyliczeniowy do schematu, zadeklaruj go 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 typu wyliczeniowego originalAspectRatio dla formatu obrazu, w którym film został nagrany, oraz inne pole otherAspectRatios dla listy innych dostępnych formatów obrazu.
Zarządzanie zmianami w polach wyliczenia
Możesz dodawać nowe wartości do typu wyliczeniowego, ale kolejność na liście jest bardzo ważna, więc wstawiaj nowe wartości z rozmysłem. Jedyną zmianą w typie wyliczeniowym, która jest w pełni zgodna wstecznie, jest dodanie nowej wartości na końcu listy wartości. Warto zauważyć, że wstawienie nowej wartości między wcześniej opublikowane wartości typu wyliczeniowego lub zmiana kolejności istniejących wartości zmienia względną kolejność, gdy w zapytaniach używane są operatory względne, takie jak „mniejsze niż”. Usuwanie lub zmiana nazw wartości zawsze powoduje brak zgodności wstecznej.
Nigdy nie należy zmieniać kolejności wartości na liście wartości typu wyliczeniowego. Kolejność jest ważna, ponieważ wpływa na sposób stosowania filtrowania.
Zmiany wartości typu wyliczeniowego należy wprowadzać ostrożnie, aby nie uszkodzić starszych wersji operacji lub kodu klienta. Podczas usuwania lub zmieniania nazwy wartości typu wyliczeniowego upewnij się, że w bieżącej bazie danych nie ma już żadnych jej wystąpień.
Używanie pól typu wyliczeniowego w operacjach i kodzie klienta
Po dodaniu pola typu wyliczeniowego do schematu możesz używać tego pola w zapytaniach i kodzie klienta.
Więcej informacji o pisaniu zapytań z użyciem typów wyliczeniowych i o tym, jak napisać klienta, aby umożliwić wprowadzanie zmian w typach wyliczeniowych, 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
SQL Connect obsługuje te skalarne typy danych, a przypisania do typów PostgreSQL są wykonywane za pomocą @col(dataType:).
| Typ SQL Connect | Wbudowany typ GraphQL lub SQL Connect typ niestandardowy |
Domyślny typ PostgreSQL | Obsługiwane typy PostgreSQL (alias w nawiasie) |
|---|---|---|---|
| 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 wektorów za pomocą Vertex AI. |
- Typ
ListGraphQL jest mapowany na tablicę jednowymiarową.- Na przykład
[Int]odpowiadaint5[], a[Any]odpowiadajsonb[]. - SQL Connect nie obsługuje zagnieżdżonych tablic.
- Na przykład
Odpowiednik schematu 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 dla aplikacji za pomocą narzędzi pomocy AI
- zapoznać się z dokumentacją składni,