Con Firebase Data Connect, puoi progettare uno schema GraphQL che rappresenta il modello di dati richiesto per la tua applicazione. Data Connect converte questo schema nell'istanza Cloud SQL per PostgreSQL che supporta la tua app. Poi, puoi creare query e mutazioni per interagire con il backend e raggruppare queste operazioni in connettori per utilizzare i dati dal codice client.
Data Connect offre strumenti di AI per aiutarti a progettare e implementare i tuoi schemi. Questa guida introduce concetti importanti di progettazione dello schema per supportare e integrare i flussi di lavoro standard e assistiti dall'AI quando inizi a sviluppare un'appe non solo.
La guida introduttiva ha presentato uno schema di app per le recensioni di film per PostgreSQL.
Questa guida sviluppa ulteriormente questo schema e fornisce un elenco SQL equivalente allo schema finale dell'app per le recensioni di film.
Lo schema per un'app per le recensioni di film
Supponiamo che tu voglia creare un servizio che consenta agli utenti di inviare e visualizzare le recensioni di film.
Per un'app di questo tipo, hai bisogno di uno schema iniziale che supporti le query di base. In un secondo momento, estenderai questo schema per creare query relazionali complesse.
In Data Connect, definirai i tipi GraphQL per definire la forma dei dati che i tuoi client possono eseguire query e manipolare. Quando scrivi lo schema, i tipi vengono convertiti in tabelle Cloud SQL per PostgreSQL, il più delle volte in una relazione diretta tra i tipi GraphQL e le tabelle di database, anche se sono possibili altre mappature. Questa guida mostra alcuni esempi, da quelli di base a quelli più avanzati.
Definire un tipo Movie di base
Puoi iniziare con un tipo Movie.
Lo schema per Movie contiene direttive di base come:
@table(name)e@col(name)per personalizzare i nomi delle tabelle e delle colonne SQL. Data Connect genera nomi snake_case se non vengono specificati.@col(dataType)per personalizzare i tipi di colonne SQL.@defaultper configurare i valori predefiniti delle colonne SQL durante l'inserimento.
Per ulteriori dettagli, consulta la documentazione di riferimento per @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
}
Archiviare automaticamente i dati utente importanti in un tipo User
La tua app terrà traccia degli utenti, quindi hai bisogno di un tipo User.
La direttiva @default è particolarmente utile in questo caso. Il campo id qui
può recuperare automaticamente l'ID utente dall'autenticazione: nota l'
utilizzo di @default(expr: "auth.uid") nell'esempio seguente.
# Users
# Suppose a user can leave reviews for movies
type User @table {
id: String! @default(expr: "auth.uid")
username: String! @col(dataType: "varchar(50)")
}
Scalari chiave e valori del server
Prima di esaminare più da vicino l'app per le recensioni di film, è importante introdurre Data Connect scalari chiave e valori del server.
Gli scalari chiave sono identificatori di oggetti concisi che Data Connect assembla automaticamente dai campi chiave degli schemi. Gli scalari chiave sono incentrati sull'efficienza e ti consentono di trovare in una singola chiamata informazioni sull'identità e la struttura dei tuoi dati. Sono particolarmente utili quando vuoi eseguire azioni sequenziali sui nuovi record e hai bisogno di un identificatore univoco da passare alle operazioni imminenti, nonché quando vuoi accedere alle chiavi relazionali per eseguire operazioni aggiuntive più complesse.
Utilizzando i valori del server, puoi consentire al server di compilare dinamicamente i
campi nelle tabelle utilizzando valori archiviati o facilmente calcolabili in base a
espressioni CEL lato server specifiche nell'argessa expr argomento. Ad esempio, puoi definire un campo con un timestamp applicato quando si accede al campo utilizzando
l'ora memorizzata in una richiesta di operazione, updatedAt: Timestamp!
@default(expr: "request.time").
Gestire le relazioni molti-a-molti nei tipi Actor e MovieActor
Ora che hai gestito gli utenti, puoi tornare alla modellazione dei dati dei film.
Poi, vuoi che gli attori recitino nei tuoi film.
La tabella Actor è piuttosto semplice.
# 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)")
}
Se vuoi che gli attori recitino in più film e che i film abbiano più attori, avrai bisogno di una "tabella di unione".
La tabella MovieActor gestisce la relazione molti-a-molti e la sua
chiave primaria è una combinazione di [movie, actor] (i campi di chiave esterna di
movie e 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
}
Quando definisci una relazione SQL nella tabella con un vincolo di chiave esterna,
Data Connect genera automaticamente il campo corrispondente dall'
altra parte. Non devi definire il campo di mappatura inversa (ad es. da
Actor a MovieActor).
Gestire le relazioni uno-a-uno in un tipo MovieMetadata
Ora, tieni traccia dei registi dei film e configura una relazione uno-a-uno con Movie.
Puoi utilizzare la direttiva @ref per personalizzare i vincoli di chiave esterna:
@ref(fields)specifica i campi di chiave esterna da utilizzare.@ref(references)specifica i campi a cui si fa riferimento nella tabella di destinazione (il valore predefinito è la chiave primaria, ma funzionano anche i campi@unique). Questa è un'opzione più avanzata; Data Connect spesso può dedurla per te.
Per ulteriori dettagli, consulta la documentazione di riferimento per @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
}
Utilizzare i campi generati dallo schema per creare operazioni
Le operazioni di Data Connect estenderanno un insieme di campi generati automaticamente da Data Connect in base ai tipi e alle relazioni tra i tipi nello schema. Questi campi vengono generati dagli strumenti locali ogni volta che modifichi lo schema.
Supponiamo che lo schema contenga un tipo Movie e un tipo Actor associato.
Data Connect genera movie, movies,
actors_on_movies campi e altri ancora.
Eseguire query con il
movie campo
|
Il campo |
Utilizza questo campo per eseguire query su un singolo film in base alla sua chiave. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Eseguire query con il campo
movies
|
Il campo |
Utilizza questo campo per eseguire query su più film, ad esempio tutti i film di un determinato anno. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Eseguire query con il
actors_on_movies campo
|
Il campo |
Utilizza questo campo per eseguire query su tutti gli attori associati a un determinato film. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Tenendo presente questo, puoi leggere come implementare le operazioni utilizzando questi campi nella guida all'implementazione delle query e guida all'implementazione delle mutazioni.
Concetti di schema più avanzati
Campi di enumerazione
Data Connect supporta i campi di enumerazione che eseguono il mapping ai tipi enumerati di PostgreSQL. Gli enum ti consentono di definire rapidamente un elenco di valori statici e predefiniti con un ordine specifico.
Per aggiungere un enum allo schema, dichiara l'enum e i relativi valori predefiniti, quindi fai riferimento ad esso nel tipo.
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
}
Nel tipo Movie, abbiamo aggiunto un campo enum originalAspectRatio per le proporzioni in cui è stato girato il film e un altro campo otherAspectRatios per un elenco di altre proporzioni disponibili.
Gestire le modifiche ai campi di enumerazione
Puoi aggiungere nuovi valori all'enum, ma l'ordine dell'elenco enum è molto significativo, quindi inserisci i nuovi valori con attenzione. L'unica modifica completamente compatibile con le versioni precedenti di un enum è l'aggiunta di un nuovo valore alla fine dell'elenco di valori. In particolare, l'inserimento di un nuovo valore tra gli enum pubblicati in precedenza o il riordino dei valori esistenti modifica l'ordinamento relativo quando vengono utilizzati operatori relativi come "minore di" nelle query. La rimozione o la ridenominazione dei valori è sempre una modifica incompatibile con le versioni precedenti.
Non devi mai riordinare i valori nell'elenco dei valori enum; l'ordinamento è importante perché modifica la modalità di applicazione del filtro.
Le modifiche ai valori enum devono essere eseguite con attenzione per non interrompere le versioni precedenti del codice dell'operazione o del client. Quando rimuovi o ridenomini un valore enum, assicurati che non siano rimaste istanze nel database corrente.
Utilizzare i campi enum nelle operazioni e nel codice client
Ora che hai aggiunto un campo enum allo schema, puoi utilizzarlo nelle query e nel codice client.
Scopri di più sulla scrittura di query che utilizzano gli enum e su come scrivere un client per consentire le modifiche agli enum a partire dalla guida alle query.
Altri concetti avanzati
Per andare oltre i tipi e le relazioni di base ma utili, consulta gli esempi in la documentazione di riferimento.
Tipi di dati supportati
Data Connect supporta i seguenti tipi di dati scalari, con
assegnazioni ai tipi PostgreSQL utilizzando @col(dataType:).
| Data Connect tipo | Tipo integrato GraphQL o Data Connect tipo personalizzato |
Tipo PostgreSQL predefinito | Tipi PostgreSQL supportati (alias tra parentesi) |
|---|---|---|---|
| Stringa | GraphQL | testo | testo bit(n), varbit(n) char(n), varchar(n) |
| Int | GraphQL | int | Int2 (smallint, smallserial), int4 (integer, int, serial) |
| In virgola mobile | GraphQL | float8 | float4 (real) float8 (double precision) numeric (decimal) |
| Booleano | GraphQL | booleano | booleano |
| UUID | Personalizzato | uuid | uuid |
| Int64 | Personalizzato | bigint | int8 (bigint, bigserial) numeric (decimal) |
| Data | Personalizzato | date | date |
| Timestamp | Personalizzato | timestamptz | timestamptz Nota: le informazioni sul fuso orario locale non vengono archiviate. |
| Enumerazione | Personalizzato | enum | enum |
| Vettoriale | Personalizzato | vettore | vettore Consulta Eseguire la ricerca di similarità vettoriale con Vertex AI. |
- GraphQL
Listesegue il mapping a un array unidimensionale.- Ad esempio,
[Int]esegue il mapping aint5[],[Any]esegue il mapping ajsonb[]. - Data Connect non supporta gli array nidificati.
- Ad esempio,
Schema SQL equivalente
-- 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);
Passaggi successivi
Potresti essere interessato a:
- Generare schemi per le tue app utilizzando gli strumenti di Assistenza AI
- Esaminare la documentazione di riferimento della sintassi.