Con Firebase SQL Connect, diseñas un esquema de GraphQL que representa el modelo de datos que requiere tu aplicación. SQL Connect convierte este esquema en la instancia de Cloud SQL para PostgreSQL que respalda tu app. Luego, crearás consultas y mutaciones para interactuar con el backend y agruparás estas operaciones en conectores para usar tus datos desde el código del cliente.
SQL Connect ofrece herramientas de IA para ayudarte a diseñar e implementar tus esquemas. En esta guía, se presentan conceptos importantes del diseño de esquemas para respaldar y complementar tus flujos de trabajo estándar y asistidos por IA cuando comienzas a desarrollar una app y más allá.
En la guía de introducción, se presentó un esquema de app de opiniones sobre películas para PostgreSQL.
En esta guía, se desarrolla aún más ese esquema y se proporciona una lista de SQL equivalente al esquema final de la app de opiniones sobre películas.
El esquema de una app de opiniones sobre películas
Imagina que quieres compilar un servicio que permita a los usuarios enviar y ver opiniones sobre películas.
Necesitas un esquema inicial para que una app de este tipo admita consultas básicas. Más adelante, extenderás este esquema para crear consultas relacionales complejas.
En SQL Connect, definirás tipos de GraphQL para definir la forma de los datos que tus clientes pueden consultar y manipular. Cuando escribes tu esquema, tus tipos se traducen a Cloud SQL para las tablas de PostgreSQL, con mayor frecuencia en una relación directa entre los tipos de GraphQL y las tablas de la base de datos, aunque es posible realizar otras asignaciones. En esta guía, se muestran algunos ejemplos, desde los más básicos hasta los más avanzados.
Define un tipo básico de Movie
Puedes comenzar con un tipo Movie.
El esquema de Movie contiene directivas principales como las siguientes:
@table(name)y@col(name)para personalizar los nombres de las tablas y columnas de SQL SQL Connect genera nombres en minúsculas con guiones bajos si no se especifica.@col(dataType)para personalizar los tipos de columnas de SQL.@defaultpara configurar los valores predeterminados de las columnas de SQL durante la inserción.
Para obtener más detalles, consulta los documentos de referencia de @table, @col y @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
}
Almacena datos importantes del usuario automáticamente en un tipo User
Tu app hará un seguimiento de los usuarios, por lo que necesitas un tipo User.
La directiva @default es especialmente útil en este caso. El campo id aquí
puede obtener automáticamente el ID del usuario de la autenticación: observa el
uso de @default(expr: "auth.uid") en el siguiente ejemplo.
# 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 claves y valores del servidor
Antes de analizar más la app de opiniones sobre películas, es importante presentar los escalares clave y los valores del servidor de SQL Connect.
Los escalares clave son identificadores de objetos concisos que SQL Connect ensambla automáticamente a partir de campos clave en tus esquemas. Los escalares clave se relacionan con la eficiencia, ya que te permiten encontrar en una sola llamada información sobre la identidad y la estructura de tus datos. Son útiles, en especial, cuando quieres realizar acciones secuenciales en registros nuevos y necesitas un identificador único para pasar a las próximas operaciones, y también cuando quieres acceder a claves relacionales para realizar operaciones adicionales más complejas.
Con los valores del servidor, puedes permitir que el servidor complete de forma dinámica
los campos de tus tablas con valores almacenados o que se puedan calcular con facilidad según
expresiones de CEL particulares del servidor en el argumento expr. Por ejemplo, puedes
definir un campo con una marca de tiempo que se aplique cuando se acceda al campo con
la hora almacenada en una solicitud de operación, updatedAt: Timestamp!
@default(expr: "request.time").
Controlar las relaciones de varios a varios en los tipos Actor y MovieActor
Una vez que hayas controlado los usuarios, puedes volver a modelar los datos de las películas.
A continuación, quieres que los actores protagonicen tus películas.
La tabla Actor es bastante sencilla.
# 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)")
}
Si quieres que los actores participen en varias películas y que las películas tengan varios actores, necesitarás una "tabla de unión".
La tabla MovieActor controla la relación varios a varios, y su clave primaria es una combinación de [movie, actor] (los campos de clave externa de movie y 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
}
Cuando defines una relación de SQL en la tabla con una restricción de clave externa,
SQL Connect genera automáticamente el campo correspondiente en el
otro lado. No es necesario definir el campo de asignación inversa (p.ej., de
Actor a MovieActor).
Controla las relaciones uno a uno en un tipo MovieMetadata
Ahora, haz un seguimiento de los directores de películas y configura una relación uno a uno con Movie.
Puedes usar la directiva @ref para personalizar las restricciones de clave externa:
@ref(fields)especifica qué campos de clave externa se deben usar.@ref(references)especifica los campos a los que se hace referencia en la tabla de destino (el valor predeterminado es la clave primaria, pero los campos@uniquetambién funcionan). Esta es una opción más avanzada; SQL Connect suele inferir esto por ti.
Para obtener más detalles, consulta los documentos de referencia de @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
}
Usa los campos generados a partir de tu esquema para crear operaciones
Tus operaciones SQL Connect extenderán un conjunto de campos generados automáticamente por SQL Connect según los tipos y las relaciones de tipos en tu esquema. Las herramientas locales generan estos campos cada vez que editas tu esquema.
Supongamos que tu esquema contiene un tipo Movie y un tipo Actor asociado.
SQL Connect genera los campos movie, movies,
actors_on_movies y más.
Consulta con el campo
movie
|
El campo |
Usa este campo para consultar una sola película por su clave. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Consulta con el campo
movies
|
El campo |
Usa este campo para consultar varias películas, por ejemplo, todas las películas de un año determinado. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Consulta con el campo
actors_on_movies
|
El campo |
Usa este campo para consultar todos los actores asociados con una película determinada. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Con esto en mente, puedes leer cómo implementar operaciones con estos campos en la guía para implementar consultas y la guía para implementar mutaciones.
Conceptos de esquemas más avanzados
Campos de enumeración
SQL Connect admite campos de enumeración que se asignan a tipos enumerados de PostgreSQL. Los Enums te permiten definir rápidamente una lista de valores estáticos y predefinidos con un orden específico.
Para agregar un enum a tu esquema, decláralo y sus valores predefinidos, luego, haz referencia a él en tu 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
}
En el tipo Movie, agregamos un campo de tipo enum originalAspectRatio para la relación de aspecto en la que se filmó la película y otro campo otherAspectRatios para una lista de otras relaciones de aspecto disponibles.
Administra los cambios en los campos de enumeración
Puedes agregar valores nuevos a tu enum, pero el orden de la lista de enum es muy significativo, por lo que debes insertar los valores nuevos con cuidado. El único cambio totalmente retrocompatible en un enum es agregar un valor nuevo al final de la lista de valores. En particular, insertar un valor nuevo entre enumeraciones publicadas anteriormente o reordenar los valores existentes cambia el orden relativo cuando se usan operadores relativos, como "menor que", en las consultas. Quitar o cambiar el nombre de los valores siempre es un cambio incompatible con versiones anteriores.
Nunca debes reordenar los valores de la lista de valores de la enumeración; el orden es importante, ya que cambia la forma en que se aplica el filtrado.
Los ajustes en los valores de enum deben realizarse con cuidado para no dañar las versiones anteriores de tu operación o código de cliente. Cuando quites o cambies el nombre de un valor de enum, asegúrate de que no queden instancias en tu base de datos actual.
Usa tus campos de tipo enum en operaciones y en el código del cliente
Ahora que agregaste un campo de tipo enum a tu esquema, puedes usarlo en consultas y código de cliente.
Obtén más información para escribir consultas con enums y cómo escribir un cliente que permita ajustes en tus enums en la guía de consultas.
Otros conceptos avanzados
Para ir más allá de los tipos y las relaciones básicos, pero útiles, consulta los ejemplos en la documentación de referencia.
Tipos de datos admitidos
SQL Connect admite los siguientes tipos de datos escalares, con
asignaciones a tipos de PostgreSQL con @col(dataType:).
| Tipo SQL Connect | Tipo integrado de GraphQL o SQL Connect tipo personalizado |
Tipo de PostgreSQL predeterminado | Tipos de PostgreSQL admitidos (alias entre paréntesis) |
|---|---|---|---|
| String | GraphQL | texto | text bit(n), varbit(n) char(n), varchar(n) |
| Int | GraphQL | int | Int2 (smallint, smallserial), int4 (integer, int, serial) |
| Número de punto flotante | GraphQL | float8 | float4 (real) float8 (precisión doble) numeric (decimal) |
| Booleano | GraphQL | booleano | booleano |
| UUID | Personalizado | uuid | uuid |
| Int64 | Personalizado | bigint | int8 (bigint, bigserial) numeric (decimal) |
| Fecha | Personalizado | date | fecha |
| Marca de tiempo | Personalizado | timestamptz | timestamptz Nota: No se almacena la información de la zona horaria local. |
| Enumeration | Personalizado | enum | enum |
| Vector | Personalizado | vector | vector Consulta Realiza una búsqueda de similitud de vectores con Vertex AI. |
- El
Listde GraphQL se asigna a un array unidimensional.- Por ejemplo,
[Int]se asigna aint5[],[Any]se asigna ajsonb[]. - SQL Connect no admite arrays anidados.
- Por ejemplo,
Esquema de 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óximos pasos
Tal vez te interese:
- Genera esquemas para tus apps con herramientas de asistencia de IA
- Revisa la documentación de referencia de la sintaxis.