С помощью Firebase Data Connect вы разрабатываете схему GraphQL, которая представляет собой модель данных, необходимую для вашего приложения. Data Connect преобразует эту схему в экземпляр Cloud SQL for PostgreSQL, который используется в вашем приложении. Затем вы создаете запросы и мутации для взаимодействия с бэкэндом и объединяете эти операции в коннекторы для использования ваших данных из клиентского кода.
Data Connect предлагает инструменты искусственного интеллекта, которые помогут вам проектировать и внедрять схемы. Это руководство знакомит с важными концепциями проектирования схем, которые поддержат и дополнят ваши стандартные и автоматизированные рабочие процессы при разработке приложения и в дальнейшем .
В руководстве по началу работы была представлена схема приложения для написания отзывов о фильмах для PostgreSQL.
В этом руководстве схема дорабатывается, и приводится SQL-код, эквивалентный окончательной схеме приложения для обзоров фильмов.
Схема приложения для написания отзывов о фильмах.
Представьте, что вы хотите создать сервис, который позволит пользователям оставлять и просматривать отзывы о фильмах.
Для поддержки базовых запросов такому приложению необходима начальная схема. Позже вы расширите эту схему для создания сложных реляционных запросов.
В Data Connect вы определяете типы GraphQL, чтобы задать структуру данных, которые ваши клиенты могут запрашивать и обрабатывать. При написании схемы ваши типы преобразуются в таблицы Cloud SQL для 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) char(n), varchar(n) |
| Интерн. | GraphQL | инт | Int2 (smallint, smallserial), int4 (integer, int, serial) |
| Плавать | GraphQL | float8 | float4 (real) float8 (двойная точность) числовой (десятичный) |
| Логический | GraphQL | булев | булев |
| UUID | Обычай | uuid | uuid |
| Int64 | Обычай | бигинт | int8 (bigint, bigserial) числовой (десятичный) |
| Дата | Обычай | дата | дата |
| Отметка времени | Обычай | timestamptz | timestamptz Примечание: информация о местном часовом поясе не сохраняется. |
| Перечисление | Обычай | перечисление | перечисление |
| Вектор | Обычай | вектор | вектор См. раздел «Выполнение поиска векторного сходства с помощью Vertex AI» . |
- GraphQL
Listпреобразует данные в одномерный массив.- Например,
[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);
Следующие шаги
Возможно, вас заинтересует:
- Создание схем для ваших приложений с помощью инструментов искусственного интеллекта.
- Изучение справочной документации по синтаксису .