Com o Firebase Data Connect, você cria um esquema do GraphQL que representa o modelo de dados necessário para seu aplicativo. O Data Connect converte esse esquema na instância do Cloud SQL para PostgreSQL que oferece suporte ao seu app. Em seguida, você cria consultas e mutações para interagir com o back-end e agrupa essas operações em conectores para usar seus dados do código do cliente.
O Data Connect oferece ferramentas de IA para ajudar você a projetar e implementar seus esquemas. Este guia apresenta conceitos importantes de design de esquema para apoiar e complementar seus fluxos de trabalho padrão e com auxílio de IA quando você começar a desenvolver um app e depois.
O guia de início rápido apresentou um esquema de app de avaliação de filmes para PostgreSQL.
Este guia desenvolve ainda mais esse esquema e fornece uma listagem de SQL equivalente ao esquema final do app de avaliação de filmes.
O esquema de um app de avaliação de filmes
Imagine que você quer criar um serviço que permita aos usuários enviar e ver avaliações de filmes.
Você precisa de um esquema inicial para que um app desse tipo possa oferecer suporte a consultas básicas. Você vai estender esse esquema mais tarde para criar consultas relacionais complexas.
Em Data Connect, você vai definir tipos do GraphQL para definir o formato dos dados que seus clientes podem consultar e manipular. Ao escrever seu esquema, os tipos são traduzidos para tabelas do Cloud SQL para PostgreSQL, geralmente em uma relação direta entre tipos do GraphQL e tabelas de banco de dados, embora outros mapeamentos sejam possíveis. Este guia mostra alguns exemplos, desde o básico até o mais avançado.
Definir um tipo Movie
básico
Você pode começar com um tipo de Movie
.
O esquema de Movie
contém diretivas principais, como:
@table(name)
e@col(name)
para personalizar os nomes da tabela e das colunas SQL. A Conexão de dados gera nomes snake_case se não forem especificados.@col(dataType)
para personalizar tipos de coluna SQL.@default
para configurar valores padrão de coluna SQL durante a inserção.
Para mais detalhes, consulte os documentos de referência de @table
, @col
e @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
}
Armazenar automaticamente dados importantes do usuário em um tipo User
O app vai acompanhar os usuários, então você precisa de um tipo User
.
A diretiva @default
é especialmente útil nesse caso. O campo id
aqui
pode buscar automaticamente o ID do usuário na autenticação. Observe o
uso de @default(expr: "auth.uid")
no exemplo a seguir.
# Users
# Suppose a user can leave reviews for movies
type User @table {
id: String! @default(expr: "auth.uid")
username: String! @col(dataType: "varchar(50)")
}
Escalares de chave e valores do servidor
Antes de analisar mais o app de avaliação de filmes, é importante apresentar os escalares de chave e os valores do servidor do Data Connect.
Escalares de chave são identificadores de objetos concisos que o Data Connect monta automaticamente com base em campos-chave nos seus esquemas. Os escalares principais são sobre eficiência, permitindo que você encontre em uma única chamada informações sobre a identidade e a estrutura dos seus dados. Elas são especialmente úteis quando você quer realizar ações sequenciais em novos registros e precisa de um identificador exclusivo para transmitir às próximas operações, e também quando quer acessar chaves relacionais para realizar outras operações mais complexas.
Usando valores do servidor, você pode permitir que o servidor preencha dinamicamente
campos nas suas tabelas usando valores armazenados ou facilmente calculáveis de acordo com
expressões CEL específicas do lado do servidor no argumento expr
. Por exemplo, é possível definir um campo com um carimbo de data/hora aplicado quando ele é acessado usando o tempo armazenado em uma solicitação de operação, updatedAt: Timestamp!
@default(expr: "request.time")
.
Processar relações de muitos para muitos nos tipos Actor
e MovieActor
Com os usuários processados, você pode voltar a modelar os dados de filmes.
Em seguida, você vai querer atores para estrelar seus filmes.
A tabela Actor
é bem direta.
# 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 você quiser que atores estejam em vários filmes e que os filmes tenham vários atores, será necessário usar uma "tabela de junção".
A tabela MovieActor
processa o relacionamento muitos para muitos, e a chave primária dela é uma combinação de [movie, actor]
(os campos de chave externa de 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 você define uma relação SQL na tabela com uma restrição de chave externa, o Data Connect gera automaticamente o campo correspondente do outro lado. Não é necessário definir o campo de mapeamento inverso (por exemplo, de Actor
para MovieActor
).
Processar relações de um para um em um tipo MovieMetadata
Agora, acompanhe os diretores de cinema e configure uma relação um para um com Movie
.
É possível usar a diretiva @ref
para personalizar restrições de chave estrangeira:
@ref(fields)
especifica quais campos de chave estrangeira usar.@ref(references)
especifica os campos referenciados na tabela de destino (o padrão é a chave primária, mas os campos@unique
também funcionam). Essa é uma opção mais avançada. O Data Connect geralmente pode inferir isso para você.
Para mais detalhes, consulte os documentos de referência do @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
}
Usar campos gerados do seu esquema para criar operações
Suas operações Data Connect vão estender um conjunto de campos Data Connect gerados automaticamente com base nos tipos e nas relações de tipo no seu esquema. Esses campos são gerados por ferramentas locais sempre que você edita o esquema.
Suponha que seu esquema contenha um tipo Movie
e um tipo Actor
associado.
O Data Connect gera campos movie
, movies
, actors_on_movies
e muito mais.
Consultar com o campo
movie
O campo |
Use este campo para consultar um único filme pela chave. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Consultar com o campo
movies
O campo |
Use esse campo para consultar vários filmes, por exemplo, todos os filmes de um determinado ano. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Consultar com o campo
actors_on_movies
O campo |
Use este campo para consultar todos os atores associados a um determinado filme. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Com isso em mente, leia como implementar operações usando esses campos no guia de implementação de consultas e no guia de implementação de mutações.
Conceitos de esquema mais avançados
Campos de enumeração
O Data Connect é compatível com campos de enumeração que são mapeados para tipos enumerados do PostgreSQL. Com as enumerações, é possível definir rapidamente uma lista de valores estáticos predefinidos com uma ordem específica.
Para adicionar uma enumeração ao seu esquema, declare a enumeração e os valores predefinidos dela e faça referência a ela no seu 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
}
No tipo Movie
, adicionamos um campo de enumeração originalAspectRatio
para a proporção
de tela em que o filme foi gravado e outro campo otherAspectRatios
para
uma lista de outras proporções de tela disponíveis.
Gerenciar mudanças em campos de enumeração
É possível adicionar novos valores à enumeração, mas a ordem da lista é muito importante. Portanto, insira os novos valores com cuidado. A única mudança totalmente compatível com versões anteriores em uma enumeração é adicionar um novo valor ao final da lista de valores. Inserir um novo valor entre enums publicados anteriormente ou reordenar valores atuais muda a ordenação relativa quando operadores relativos, como "menor que", são usados em consultas. Remover ou renomear valores é sempre uma mudança incompatível com versões anteriores.
Nunca reordene os valores na lista de valores de enumeração. A ordem é importante porque muda a forma como a filtragem é aplicada.
Os ajustes nos valores de enumeração precisam ser feitos com cuidado para não interromper versões mais antigas da sua operação ou do código do cliente. Ao remover ou renomear um valor de enumeração, verifique se não há instâncias restantes no banco de dados atual.
Como usar campos de enumeração em operações e no código do cliente
Agora que você adicionou um campo de enumeração ao esquema, é possível usá-lo em consultas e código do cliente.
Saiba mais sobre como escrever consultas usando enums e como escrever um cliente para permitir ajustes nos seus enums no guia de consultas.
Outros conceitos avançados
Para ir além dos tipos e relacionamentos básicos, mas úteis, consulte os exemplos na documentação de referência.
Tipos de dados compatíveis
O Data Connect oferece suporte aos seguintes tipos de dados escalares, com atribuições a tipos do PostgreSQL usando @col(dataType:)
.
Data Connect type | Tipo integrado do GraphQL ou tipo personalizado Data Connect |
Tipo padrão do PostgreSQL | Tipos do PostgreSQL compatíveis (alias entre parênteses) |
---|---|---|---|
String | GraphQL | texto | text bit(n), varbit(n) char(n), varchar(n) |
Int | GraphQL | int | Int2 (smallint, smallserial), int4 (integer, int, serial) |
Ponto flutuante | GraphQL | float8 | float4 (real) float8 (precisão dupla) numeric (decimal) |
Booleano | GraphQL | booleano | booleano |
UUID | Personalizado | uuid | uuid |
Int64 | Personalizado | bigint | int8 (bigint, bigserial) numeric (decimal) |
Data | Personalizado | date | data |
Carimbo de data/hora | Personalizado | timestamptz | timestamptz Observação:as informações de fuso horário local não são armazenadas. |
Enumeração | Personalizado | enum | tipo enumerado |
Vetor | Personalizado | vector | vetor Consulte Realizar pesquisa de similaridade vetorial com a Vertex AI. |
- O
List
do GraphQL é mapeado para uma matriz unidimensional.- Por exemplo,
[Int]
é mapeado paraint5[]
, e[Any]
é mapeado parajsonb[]
. - Data Connect não é compatível com matrizes aninhadas.
- Por exemplo,
Esquema 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);
Próximas etapas
Talvez você se interesse por:
- Gerar esquemas para seus apps usando ferramentas de assistência de IA
- Consulte a documentação de referência de sintaxe.