С помощью Firebase Data Connect вы разрабатываете схему GraphQL, представляющую модель данных, необходимую для вашего приложения. Data Connect преобразует эту схему в экземпляр Cloud SQL для PostgreSQL, поддерживающий ваше приложение. Затем вы разрабатываете запросы и мутации для взаимодействия с бэкендом и объединяете эти операции в коннекторы для использования данных из клиентского кода.
Data Connect предлагает инструменты на основе искусственного интеллекта (ИИ), которые помогут вам разрабатывать и внедрять схемы. В этом руководстве представлены важные концепции проектирования схем, которые помогут вам поддерживать и дополнять стандартные рабочие процессы и процессы с использованием ИИ, как при разработке приложения , так и в дальнейшем .
В руководстве по началу работы представлена схема приложения для обзора фильмов для PostgreSQL.
В этом руководстве схема развивается дальше и приводится листинг SQL, эквивалентный окончательной схеме приложения для обзора фильмов.
Схема приложения для обзора фильмов
Представьте, что вы хотите создать сервис, позволяющий пользователям отправлять и просматривать обзоры фильмов.
Для поддержки базовых запросов такому приложению необходима начальная схема. Позже вы расширите эту схему для создания сложных реляционных запросов.
В Data Connect вы определите типы GraphQL , чтобы определить структуру данных, которые ваши клиенты могут запрашивать и обрабатывать. При написании схемы ваши типы транслируются в таблицы Cloud SQL for PostgreSQL, чаще всего в прямой связи между типами GraphQL и таблицами базы данных, хотя возможны и другие варианты сопоставления. В этом руководстве приведены примеры — от простых до более сложных.
Определить базовый тип Movie
Вы можете начать с типа Movie
.
Схема для Movie
содержит такие основные директивы, как:
-
@table(name)
и@col(name)
для настройки имён таблиц и столбцов SQL. Data Connect генерирует имена в формате snake_case, если не указано иное. -
@col(dataType)
для настройки типов столбцов SQL. -
@default
для настройки значений столбцов SQL по умолчанию во время вставки.
Более подробную информацию можно найти в справочной документации по @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
}
Автоматически сохранять важные пользовательские данные в типе User
Ваше приложение будет отслеживать пользователей, поэтому вам нужен тип « User
.
Директива @default
особенно полезна в этом случае. Поле id
здесь может автоматически извлекать идентификатор пользователя из аутентификации: обратите внимание на использование @default(expr: "auth.uid")
в следующем примере.
# Users
# Suppose a user can leave reviews for movies
type User @table {
id: String! @default(expr: "auth.uid")
username: String! @col(dataType: "varchar(50)")
}
Ключевые скаляры и значения сервера
Прежде чем подробнее рассмотреть приложение для обзора фильмов, важно познакомить вас с ключевыми скалярами и значениями сервера Data Connect .
Ключевые скаляры — это краткие идентификаторы объектов, которые Data Connect автоматически собирает из ключевых полей в ваших схемах. Ключевые скаляры обеспечивают эффективность, позволяя вам за один вызов находить информацию об идентификаторах и структуре ваших данных. Они особенно полезны, когда вы хотите выполнять последовательные действия с новыми записями и вам нужен уникальный идентификатор для передачи в последующие операции, а также когда вам требуется доступ к реляционным ключам для выполнения дополнительных более сложных операций.
Используя серверные значения , вы фактически позволяете серверу динамически заполнять поля в ваших таблицах, используя сохранённые или легко вычисляемые значения в соответствии с определёнными серверными CEL-выражениями в аргументе expr
. Например, вы можете определить поле с меткой времени, которая будет применяться при доступе к нему, используя время, сохранённое в запросе операции, updatedAt: Timestamp! @default(expr: "request.time")
.
Обработка отношений «многие ко многим» в типах Actor
и MovieActor
Разобравшись с пользователями, можно вернуться к моделированию данных фильмов.
Далее вы хотите, чтобы в ваших фильмах снимались актеры.
Таблица Actor
довольно проста.
# 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)")
}
Если вы хотите, чтобы актеры снимались в нескольких фильмах, а в фильмах было несколько актеров, вам понадобится «таблица объединения».
Таблица MovieActor
обрабатывает отношение «многие ко многим» , а ее первичный ключ представляет собой комбинацию [movie, actor]
(поля внешнего ключа из movie
и 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
}
При определении SQL-связи для таблицы с ограничением внешнего ключа Data Connect автоматически генерирует соответствующее поле на другой стороне. Вам не нужно определять поле обратного сопоставления (например, из Actor
обратно в MovieActor
).
Обработка отношений «один к одному» в типе MovieMetadata
Теперь следите за режиссерами фильмов, а также настройте индивидуальную связь с Movie
.
Для настройки ограничений внешнего ключа можно использовать директиву @ref
:
-
@ref(fields)
указывает, какие поля внешнего ключа следует использовать. -
@ref(references)
указывает поля, на которые ссылаются в целевой таблице (по умолчанию это первичный ключ, но поля@unique
тоже работают). Это более продвинутый вариант; Data Connect часто может определить его автоматически.
Более подробную информацию можно найти в справочной документации по @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
}
Используйте поля, созданные на основе вашей схемы, для построения операций.
Ваши операции Data Connect расширят набор полей, автоматически генерируемых Data Connect на основе типов и взаимосвязей типов в вашей схеме. Эти поля генерируются локальными инструментами при каждом редактировании схемы.
Предположим, что ваша схема содержит тип Movie
и связанный с ним тип Actor
. Data Connect генерирует поля movie
, movies
, actors_on_movies
и другие.
Запрос с
movie
Поле | Используйте это поле для запроса отдельного фильма по его ключу. query GetMovie($myKey: Movie_Key!) { movie(key: $myKey) { title } } |
Запрос с
поле movies
Поле | Используйте это поле для запроса нескольких фильмов, например, всех фильмов заданного года. query GetMovies($myYear: Int!) { movies(where: { year: { eq: $myYear } }) { title } } |
Запрос с
поле actors_on_movies
Поле | Используйте это поле для запроса всех актеров, связанных с заданным фильмом. query GetActorsOnMovie($myKey: Movie_Key!) { actors_on_movies(where: { movie: { key: { eq: $myKey } } }) { actor { name } } } |
Имея это в виду, вы можете прочитать, как реализовать операции с использованием этих полей в руководстве по реализации запросов и руководстве по реализации мутаций .
Более продвинутые концепции схем
Поля перечисления
Data Connect поддерживает поля перечисления, соответствующие перечисляемым типам PostgreSQL. Перечисления позволяют быстро определить список статических предопределённых значений в определённом порядке.
Чтобы добавить перечисление в схему, объявите перечисление и его предопределенные значения, а затем сошлитесь на него в вашем типе.
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
}
В типе Movie
мы добавили поле перечисления originalAspectRatio
для соотношения сторон, в котором был снят фильм, и еще одно поле otherAspectRatios
для списка других доступных соотношений сторон.
Управление изменениями в полях перечисления
Вы можете добавлять новые значения в перечисление, но порядок в списке перечислений очень важен, поэтому добавляйте новые значения обдуманно. Единственное полностью обратно совместимое изменение перечисления — это добавление нового значения в конец списка значений. В частности, вставка нового значения между ранее опубликованными перечислениями или изменение порядка существующих значений изменяет относительный порядок при использовании в запросах относительных операторов, таких как «меньше чем». Удаление или переименование значений всегда является обратно несовместимым изменением.
Никогда не следует изменять порядок значений в списке значений перечисления; порядок важен, поскольку он меняет способ применения фильтрации.
Изменения значений перечисления следует вносить осторожно, чтобы не повредить старые версии операционной системы или клиентского кода. При удалении или переименовании значения перечисления убедитесь, что в текущей базе данных не осталось его экземпляров.
Использование полей перечисления в операциях и клиентском коде
Теперь, когда вы добавили поле перечисления в свою схему, вы можете использовать это поле в запросах и клиентском коде.
Дополнительную информацию о написании запросов с использованием перечислений и о том, как написать клиент, позволяющий вносить изменения в перечисления, можно найти в руководстве по запросам .
Другие продвинутые концепции
Чтобы выйти за рамки базовых, но полезных типов и отношений, обратитесь к примерам в справочной документации .
Поддерживаемые типы данных
Data Connect поддерживает следующие скалярные типы данных с назначением типов PostgreSQL с помощью @col(dataType:)
.
Тип Data Connect | Встроенный тип GraphQL или Пользовательский тип Data Connect | Тип PostgreSQL по умолчанию | Поддерживаемые типы PostgreSQL (псевдоним в скобках) |
---|---|---|---|
Нить | GraphQL | текст | текст бит(n), варбит(n) символ(n), varchar(n) |
Инт | GraphQL | инт | Int2 (smallint, smallserial), int4 (целое, целое, последовательное) |
Плавать | GraphQL | float8 | float4 (действительный) float8 (двойная точность) числовой (десятичный) |
Булевое значение | GraphQL | булев | булев |
UUID | Обычай | uuid | uuid |
Int64 | Обычай | bigint | int8 (bigint, bigserial) числовой (десятичный) |
Дата | Обычай | дата | дата |
Метка времени | Обычай | timestamptz | timestamptz Примечание: информация о местном часовом поясе не сохраняется. |
Перечисление | Обычай | перечисление | перечисление |
Вектор | Обычай | вектор | вектор См. раздел Выполнение поиска сходства векторов с помощью Vertex AI . |
-
List
GraphQL отображается в одномерный массив.- Например,
[Int]
отображается вint5[]
,[Any]
отображается вjsonb[]
. - Data Connect не поддерживает вложенные массивы.
- Например,
Эквивалентная схема 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);
Следующие шаги
Вас может заинтересовать:
- Генерация схем для ваших приложений с использованием инструментов помощи ИИ
- Просмотр справочной документации по синтаксису .