SQL Connect スキーマを設計する

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

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

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

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

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

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

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

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

基本的な Movie タイプを定義する

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

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

  • @table(name)@col(name) を使用して、SQL テーブル名と列名をカスタマイズします。 SQL 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 ディレクティブが特に便利です。次のサンプルでは @default(expr: "auth.uid") を使用していることに注意してください。ここで、id フィールドは認証からユーザー ID を自動的に取得できます。

# 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キー スカラーとサーバー値を紹介します。

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

サーバー値を使用すると、 引数で特定のサーバーサイド 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]movieactor の外部キーフィールド)の組み合わせです。

# 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 との一対一 の関係を設定します。

@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 は、moviemoviesactors_on_movies フィールドなどを生成します。


movie フィールドでクエリを実行する

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

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

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 は、次のスカラーデータ型をサポートしています。PostgreSQL タイプへの割り当てには @col(dataType:) を使用します。

SQL Connect タイプ GraphQL 組み込みタイプまたは
SQL Connect カスタムタイプ
デフォルトの PostgreSQL タイプ サポートされている PostgreSQL タイプ
(かっこ内はエイリアス)
文字列 GraphQL テキスト テキスト
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 date
タイムスタンプ カスタム タイムゾーン付きタイムスタンプ

タイムゾーン付きタイムスタンプ

注: ローカル タイムゾーン情報は保存されません。
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);

次のステップ

次のトピックもご覧ください。