Dzięki Firebase SQL Connect możesz zaprojektować schemat GraphQL, który będzie reprezentować model danych wymagany przez Twoją 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 komunikować się z backendem, i łączysz te operacje w konektory, aby używać danych z kodu klienta.
SQL Connect oferuje narzędzia oparte na 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 jej utworzeniu.
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 oceniania filmów.
Schemat aplikacji do oceniania filmów
Wyobraź sobie, że chcesz utworzyć usługę, która umożliwia użytkownikom przesyłanie i wyświetlanie ocen filmów.
Aby obsługiwać podstawowe zapytania, potrzebujesz początkowego schematu takiej aplikacji. Później rozszerzysz ten schemat, aby tworzyć złożone zapytania relacyjne.
W SQL Connect zdefiniujesz typy GraphQL, aby określić kształt danych, o które klienci mogą wysyłać zapytania i którymi mogą manipulować. Gdy piszesz schemat, Twoje typy są tłumaczone na Cloud SQL dla tabel PostgreSQL, naj częś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.
Definiowanie podstawowego typu Movie
Możesz zacząć od typu Movie.
Schemat Movie zawiera podstawowe dyrektywy, takie jak:
@table(name)i@col(name)do dostosowywania nazw tabel i kolumn SQL. SQL Connect generuje nazwy w formacie snake_case, jeśli nie zostaną określone.@col(dataType)do dostosowywania typów kolumn SQL.@defaultdo konfigurowania domyślnych wartości kolumn SQL podczas wstawiania.
Więcej informacji znajdziesz w dokumentacji referencyjnej dotyczącej dyrektyw @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
}
Automatyczne przechowywanie ważnych danych użytkownika w typie User
Twoja aplikacja będzie śledzić użytkowników, dlatego 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 oceniania filmów, warto przedstawić SQL Connect kluczowe skalary i wartości serwera.
Kluczowe skalary to zwięzłe identyfikatory obiektów, które SQL Connect automatycznie tworzy na podstawie kluczowych pól w Twoich schematach. Kluczowe skalary zwiększają wydajność, ponieważ umożliwiają znalezienie w jednym wywołaniu 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 przekazania 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 pozwolić 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ą stosowaną, gdy pole jest dostępne za pomocą czasu przechowywanego 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.
Następnie chcesz, aby aktorzy występowali 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 łączenia”.
Tabela MovieActor obsługuje relację wiele do wielu, a jej
klucz podstawowy jest kombinacją [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,
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 śledź reżyserów filmów i skonfiguruj relację jeden do jednego z tabelą Movie.
Możesz użyć dyrektywy @ref, aby dostosować ograniczenia klucza obcego:
@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 działają też pola@unique). Jest to opcja bardziej zaawansowana. SQL Connect często może ją wywnioskować.
Więcej informacji znajdziesz w dokumentacji referencyjnej dotyczącej dyrektywy @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 będą rozszerzać zestaw pól automatycznie generowanych przez SQL Connect na podstawie typów i relacji między typami w Twoim schemacie. Pola te są generowane przez narzędzia lokalne za każdym razem, gdy edytujesz schemat.
Załóżmy, że Twój schemat zawiera typ Movie i powiązany z nim typ Actor.
SQL Connect generuje movie, movies,
actors_on_movies pola i inne.
Zapytanie z użyciem pola
movie
|
Pole |
Użyj tego pola, aby wysłać zapytanie o pojedynczy film według jego klucza. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Zapytanie z użyciem pola
movies
|
Pole |
Użyj tego pola, aby wysłać zapytanie o wiele filmów, np. wszystkie filmy z danego roku. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Zapytanie z użyciem pola
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 implementowaniu zapytań i przewodniku po implementowaniu mutacji.
Bardziej zaawansowane koncepcje schematów
Pola wyliczeniowe
SQL 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ć typ wyliczeniowy do schematu, zadeklaruj typ wyliczeniowy i jego wstępnie zdefiniowane wartości, a następnie odwołaj się do niego w swoim 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 proporcji obrazu, w jakich film został nakręcony, oraz inne pole otherAspectRatios dla listy innych dostępnych proporcji obrazu.
Zarządzanie zmianami w polach wyliczeniowych
Możesz dodawać nowe wartości do wyliczenia, ale kolejność listy wyliczeń jest bardzo ważna, dlatego dodawaj nowe wartości z rozwagą. Jedyną zmianą w wyliczeniu, która jest w pełni zgodna z poprzednimi wersjami, jest dodanie nowej wartości na końcu listy wartości. W szczególnoś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 są używane operatory względne, takie jak „mniejsze niż”. Usuwanie lub zmienianie nazw wartości zawsze powoduje zmianę niezgodną z poprzednimi wersjami.
Nigdy nie zmieniaj kolejności wartości na liście wartości wyliczenia. Kolejność jest ważna, ponieważ zmienia sposób stosowania filtrowania.
Dostosowywanie wartości wyliczenia należy przeprowadzać ostrożnie, aby nie spowodować niezgodności ze starszymi wersjami operacji lub 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 pola wyliczeniowego do schematu możesz używać tego pola w zapytaniach i kodzie klienta.
Więcej informacji o tworzeniu zapytań za pomocą wyliczeń oraz o tym, jak napisać klienta, który umożliwi 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 referencyjnej.
Obsługiwane typy danych
SQL Connect obsługuje te skalarne typy danych z
przypisaniami do typów PostgreSQL za pomocą @col(dataType:).
| SQL Connect typ | Wbudowany typ GraphQL lub SQL Connect niestandardowy typ |
Domyślny typ PostgreSQL | Obsługiwane typy PostgreSQL (alias w nawiasach) |
|---|---|---|---|
| Ciąg znaków | GraphQL | tekst | tekst bit(n), varbit(n) char(n), varchar(n) |
| Liczba całkowita | GraphQL | liczba całkowita | 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 | data | data |
| Sygnatura czasowa | Niestandardowy | timestamptz | timestamptz Uwaga: informacje o lokalnej strefie czasowej nie są przechowywane. |
| Wyliczenie | Niestandardowy | enum | enum |
| Wektor | Niestandardowy | wektor | wektor Zobacz Wykonywanie wyszukiwania podobieństw wektorowych za pomocą Vertex AI. |
- GraphQL
Listjest mapowany na tablicę jednowymiarową.- Na przykład
[Int]jest mapowany naint5[], a[Any]najsonb[]. - SQL Connect nie obsługuje tablic zagnieżdżonych.
- Na przykład
Odpowiednik w języku 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
- Zapoznanie się z dokumentacją referencyjną składni.