SQL Connect スキーマを設計する

Firebase SQL Connect では、アプリケーションに必要なデータモデルを表す GraphQL スキーマを設計します。SQL Connect は、このスキーマをアプリをサポートする Cloud SQL for PostgreSQL インスタンスに変換します。次に、バックエンドとやり取りするクエリとミューテーションを作成し、これらのオペレーションをコネクタにバンドルして、クライアント コードからデータを使用します。

SQL Connect には、スキーマの設計と実装に役立つ AI ツールが用意されています。このガイドでは、アプリの開発を開始する際やそれ以降に、標準のワークフローと AI を活用したワークフローをサポートして補完するスキーマ設計の重要なコンセプトについて説明します。

スタートガイドでは、PostgreSQL の映画レビューアプリのスキーマを紹介しました。

このガイドでは、そのスキーマをさらに発展させ、最終的な映画レビューアプリのスキーマに相当する SQL リストを提供します。

映画レビューアプリのスキーマ

ユーザーが映画のレビューを送信して閲覧できるサービスを構築するとします。

このようなアプリで基本的なクエリをサポートするには、初期スキーマが必要です。このスキーマは、後で拡張して複雑なリレーショナル クエリを作成します。

SQL Connect では、GraphQL タイプを定義して、クライアントがクエリと操作を行うデータの形状を定義します。スキーマを記述すると、型は PostgreSQL テーブルの Cloud SQL に変換されます。ほとんどの場合、GraphQL 型とデータベース テーブルの直接的な関係になりますが、他のマッピングも可能です。このガイドでは、基本的な例から高度な例までいくつか紹介します。

基本的な Movie 型を定義する

Movie タイプから始めることができます。

Movie のスキーマには、次のようなコア ディレクティブが含まれています。

  • @table(name) と @col(name)。SQL のテーブル名と列名をカスタマイズします。SQL Connect は、指定されていない場合、スネークケース名を生成します。
  • @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 フィールドは認証からユーザーの 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)")
}

主要なスカラーとサーバー値

映画レビューアプリについて詳しく見る前に、SQL Connect のキースカラーとサーバー値について説明しておく必要があります。

キースカラーは、SQL Connect がスキーマのキーフィールドから自動的に組み立てる簡潔なオブジェクト識別子です。キースカラーは効率性に関するもので、1 回の呼び出しでデータの ID と構造に関する情報を取得できます。これらは、新しいレコードに対して順次アクションを実行し、今後のオペレーションに渡す固有識別子が必要な場合や、リレーショナル キーにアクセスしてより複雑なオペレーションを実行する場合に特に便利です。

サーバー値を使用すると、expr 引数内の特定のサーバーサイド CEL 式に従って、保存された値または簡単に計算可能な値を使用して、サーバーがテーブル内のフィールドを動的に入力できます。たとえば、オペレーション リクエスト 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 関係を定義すると、SQL Connect は反対側に対応するフィールドを自動的に生成します。逆マッピング フィールド(Actor から MovieActor など)を定義する必要はありません。

MovieMetadata 型で 1 対 1 の関係を処理する

次に、映画監督を追跡し、Movie との 1 対 1 の関係を設定します。

@ref ディレクティブを使用すると、外部キー制約をカスタマイズできます。

  • @ref(fields) は、使用する外部キー フィールドを指定します。
  • @ref(references) は、ターゲット テーブルで参照されるフィールドを指定します(デフォルトは主キーですが、@unique フィールドも機能します)。これはより高度なオプションです。SQL 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
}

スキーマから生成されたフィールドを使用してオペレーションを構築する

SQL Connect オペレーションは、スキーマのタイプとタイプの関係に基づいて SQL Connect によって自動的に生成された一連のフィールドを拡張します。これらのフィールドは、スキーマを編集するたびにローカル ツールによって生成されます。

スキーマに Movie タイプと関連する Actor タイプが含まれているとします。SQL Connect は、movie、movies、actors_on_movies フィールドなどを生成します。


movie フィールドを使用したクエリ

movie フィールドは、Movie テーブルの 1 つのレコードを表します。

このフィールドを使用して、キーで 1 つの映画をクエリします。

query GetMovie($myKey: Movie_Key!) {
  movie(key: $myKey) { title }
}


movies フィールドを使用したクエリ

movies フィールドは、Movie テーブルのレコードのリストを表します。

このフィールドを使用して、複数の映画(特定の年のすべての映画など)をクエリします。

query GetMovies($myYear: Int!) {
  movies(where: { year: { eq: $myYear } }) { title }
}


actors_on_movies フィールドを使用したクエリ

actors_on_movies フィールドは、Actor テーブルと Movie テーブルを接続するレコードのリストを表します。このフィールドを使用して、特定の映画に関連付けられているすべての俳優をクエリします。

このフィールドを使用して、特定の映画に関連付けられているすべての俳優をクエリします。

  query GetActorsOnMovie($myKey: Movie_Key!) {
    actors_on_movies(where: { movie: { key: { eq: $myKey } } }) {
      actor { name }
    }
  }

これを念頭に置いて、クエリの実装ガイドとミューテーションの実装ガイドで、これらのフィールドを使用してオペレーションを実装する方法を確認してください。

より高度なスキーマのコンセプト

列挙フィールド

SQL 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 を追加しました。

列挙型フィールドの変更を管理する

列挙型に新しい値を追加できますが、列挙型リストの順序は非常に重要であるため、新しい値は慎重に挿入してください。列挙型に対する完全な下位互換性のある変更は、値のリストの末尾に新しい値を追加することだけです。特に、以前に公開された列挙型の間に新しい値を挿入したり、既存の値を並べ替えたりすると、クエリで「未満」などの相対演算子が使用されている場合に相対的な順序が変更されます。値の削除または名前変更は、常に下位互換性のない変更です。

列挙値リストの値の順序は変更しないでください。順序は、フィルタの適用方法に影響するため重要です。

列挙値の調整は、古いバージョンのオペレーションやクライアント コードが破損しないように慎重に行う必要があります。列挙値を削除または名前変更する場合は、現在のデータベースにインスタンスが残っていないことを確認してください。

オペレーションとクライアント コードで列挙型フィールドを使用する

スキーマに列挙型フィールドを追加したので、クエリとクライアント コードでこのフィールドを使用できます。

列挙型を使用したクエリの作成方法と、列挙型の調整を許可するクライアントの作成方法については、クエリガイドをご覧ください。

その他の高度なコンセプト

基本的なタイプと関係性以外については、リファレンス ドキュメントの例をご覧ください。

サポートされるデータ型

SQL Connect は、次のスカラー データ型をサポートしています。@col(dataType:) を使用して PostgreSQL 型に割り当てられます。

SQL Connect タイプ GraphQL 組み込み型または
SQL Connect カスタム型
デフォルトの PostgreSQL タイプ サポートされている PostgreSQL の型
(かっこ内はエイリアス)
文字列 GraphQL テキスト text
bit(n)、varbit(n)
char(n)、varchar(n)
Int GraphQL int Int2(smallint、smallserial)、
int4(integer、int、serial)
浮動小数点数 GraphQL float8 float4(real)
float8(double precision)
numeric(decimal)
ブール値 GraphQL ブール値 ブール値
UUID カスタム uuid uuid
Int64 カスタム bigint int8(bigint、bigserial)
numeric(decimal)
日付 カスタム date 日付
タイムスタンプ カスタム timestamptz

timestamptz

注: ローカルのタイムゾーン情報は保存されません。
PostgreSQL は、このようなタイムスタンプを UTC に変換して保存します。

列挙 カスタム enum

enum

ベクトル カスタム ベクトル

ベクトル

Vertex AI でベクトル類似性検索を行うをご覧ください。

  • GraphQL の List は 1 次元配列にマッピングされます。
    • たとえば、[Int] は int5[] にマッピングされ、[Any] は jsonb[] にマッピングされます。
    • SQL 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);

次のステップ

あなたへのおすすめ: