3.2 GraphQLを使用したカーレース二面性ビューの作成
カーレース・アプリケーション用のチーム、ドライバおよびレースの二面性ビューを、GraphQLを使用して作成します。
GraphQLは、様々なデータベースで使用できるオープンソースの汎用問合せ言語かつデータ操作言語です。JSONリレーショナル二面性ビューを作成するために、Oracle Databaseでは、GraphQLの構文および操作のサブセットがサポートされています。「JSONリレーショナル二面性ビューに使用されるGraphQLの言語」では、サポートされているGraphQLのサブセットについて説明します。ここで説明していない構文と機能を紹介します。
GraphQL問合せおよび型定義は、GraphQLドキュメントとして表されます。ここで示すGraphQLの例は、カーレース二面性ビューを作成する場合、SQLの例に似ています。最もわかりやすい違いは構文です。
より重要な違いは、二面性ビューのGraphQL定義では、次のものを明示的に指定する必要がないということです:
-
ネストされたスカラー副問合せ。
-
子表にその親表への外部キーが1つしかない場合、外部キー列と識別列の間の表リンク。脚注1
-
SQL/JSON生成ファンクション(またはそれと同等の構文短縮)の使用。
この情報は、かわりに、全体的な二面性ビュー定義に固有のグラフ/依存性の関係からすべて推測されます。二面性ビューの基になる表によって、それらの識別列と外部キー列の間の関係に基づいて、方向を示した依存関係グラフが形成されます。ある表T-childから別の表T-parentへの外部キーは、ノードT-childからノードT-parentに向かうグラフ・エッジ(矢印)になります。
表のセットによって決定される依存関係グラフを作成する必要はありません。これは、二面性ビューを定義すると自動的に(暗黙的に)行われます。ただし、ビジュアル化に役立つことがあります。
グラフのエッジ(矢印)は、外部キー列がある表を、識別列がその外部キーのターゲットである表にリンクしています。たとえば、ノード(表) driver
からノード(表) team
への矢印は、表driver
の外部キーが表team
の主キーにリンクされていることを示します。図3-1では、矢印に外部キーおよび主キーのラベルが付いています。
JSONリレーショナル二面性ビューを定義するGraphQLコードは、GraphQL queryの形式(囲んでいるquery {
… }
コードを含まない)を取り、ビューで使用される依存関係グラフに基づいてグラフ構造を指定します。GraphQL二面性ビュー定義は、基礎となる表ごとに、サポートされているJSONドキュメントでJSONフィールドを生成するために使用される列を指定します。
GraphQLでは、ビュー定義問合せはGraphQLオブジェクト・スキーマで表されます。このスキーマは、基となる依存関係グラフと同様に、自動的に(暗黙的に)作成されます。二面性ビューの作成に使用される依存関係グラフまたはGraphQLオブジェクト・スキーマを作成または確認する必要はありませんが、それぞれについてある程度知っていると役立ちます。
GraphQLオブジェクト・スキーマは、GraphQLオブジェクト・タイプのセットで、二面性ビュー定義の場合、ビューの基礎となる表に基づいています。
二面性ビューを作成するためのGraphQL問合せ構文は、表依存関係グラフの構造を反映しており、オブジェクト・スキーマ構文に厳密に基づいています。(違いの1つは、使用される名前がSQLと互換性があることです。)
オブジェクト・スキーマでは、つまり問合せ構文では、各GraphQLオブジェクト・タイプ(表からマップされる)は、GraphQLフィールドによって名前が付けられます(JSONオブジェクトのフィールドと混同しないでください)。また、各GraphQLフィールドにはオプションで別名を指定できます。
GraphQL問合せはグラフを記述し、各ノードはタイプを指定します。グラフ内のノードの構文は、(GraphQL)フィールド名の後にそのオブジェクト・タイプが続きます。フィールドに別名がある場合は、その後にコロン(:
)を指定して、フィールド名の前に付けます。オブジェクト・タイプは、サブグラフを囲む中カッコ({
... }
)で表されます。フィールドの後にオブジェクト・タイプを指定する必要はなく、その場合はスカラーです。
GraphQLの構文は、SQLの構文とは異なります。特に、名前(識別子)の構文は異なります。GraphQL二面性ビュー定義では、GraphQL名として直接許可されていない表名および列名は、許可されている名前にマップされます。ただし、カーレースの例のようなすべてASCII英数字の単純な表名および列名は、二面性ビューのGraphQL定義で直接使用できます。
次に例を示します。
-
driverId : driver_id
別名
driverId
が前に付いたフィールドdriver_id
。 -
driver : driver {driverId : driver_id, name : name, points : points}
別名
driver
が前に付き、別名driverId
を持つフィールドdriver_id
と、それぞれフィールドと同じ名前の別名を持つフィールドname
およびpoints
が含まれるオブジェクト・タイプが後に続くフィールドdriver
。 -
driver {driverId : driver_id, name, points}
前述の例と同等です。対応するフィールド名と同じ別名は省略できます。
表に対応するオブジェクト・タイプでは、表の各列は列と同じ名前のスカラーGraphQLフィールドにマップされます。
ノート:
これらの各例では、別名driverId
が別名_id
に置き換えられます(ドキュメント識別子フィールドとして使用する場合、つまり、driver
がルート表、driver_id
が主キー列の場合)。
ノート:
GraphQLでは、カンマ(,
)は構文的にも意味的にも重要ではありません。これらはオプションであり、無視されます。読みやすくするために、このドキュメントでは、GraphQL {
…}
内のカンマを使用して、サポートされているドキュメント内の対応するJSONオブジェクトをより適切に提示します。
二面性ビューのGraphQL定義では、生成されたJSONドキュメントに単一オブジェクトを提供するノードと、そのようなオブジェクトの配列を提供するノードとの間に実際の違いはありません。{
… }
のみを使用して、ノードがGraphQLオブジェクト・タイプであることを指定できますが、これは、サポートされているJSONドキュメントでそのノードから生成されるJSONオブジェクトが1つのみであることを意味しません。
ただし、ビューがサポートするように設計されているJSONドキュメントをより厳密に反映するGraphQL二面性ビュー定義を保持するには、必要に応じて、オブジェクトの配列を提供するノードを大カッコ([
, ]
)で囲むことができます。
たとえば、{…},…
のみではなく[{…},…]
と記述すると、定義のこの部分によってドライバ・オブジェクトの配列が生成されることを示すことができます。このマニュアルでは、この規則に従っています。
これは単に人間がコードを読むためのものであることに留意してください。大カッコは、意味を成すところではオプションです。ただし、意味を成さないところで使用すると、誤りを確認できるように構文エラーが発生します。
二面性ビューのルート表は、ビュー定義のGraphQLルート・フィールドとして使用します。たとえば、チーム・ドキュメントを定義する二面性ビューの場合は、ルートとして表team
から始めます(team {…}
と記述します)。
二面性ビュー定義の場合は表名である、タイプ名(team
など)に続く{
… }
内には、生成されるJSONフィールドの作成に使用するその表の列を指定します。
したがって、列名はGraphQLフィールド名として使用します。デフォルトでは、これらは、生成するJSONフィールドの名前にもなります。
必要なJSONフィールドの名前がその値を提供する列(GraphQLフィールド)の名前と同じでない場合は、列名の前に必要なJSONフィールドの名前を付け、2つの名前をコロン(:
)で区切ります。つまり、GraphQL別名を使用して、目的のJSONフィールド名を指定します。
たとえば、driverId : driver_id
は、列driver_id
のデータからJSONフィールドdriverId
を生成することを意味します。GraphQL用語では、driverId
は、(GraphQL)フィールドdriver_id
の別名です。
-
driver_id
のみを使用すると、その名前の列からJSONフィールドdriver_id
を生成することを意味します。 -
driverId : driver_id
を使用すると、列driver_id
のデータからJSONフィールドdriverId
を生成することを意味します。GraphQL用語では、driverId
は、GraphQLフィールドdriver_id
の別名です。
GraphQL問合せを作成して二面性ビューを作成する場合は、JSONフィールドをサポートする表依存関係グラフの列ごとにGraphQLフィールドを追加します。
さらに、二面性ビュー定義で使用される各表Tについて:
-
Tから親表T-parentへの外部キー・リンクごとに、T-parentという名前のフィールドを問合せに追加して、TからT-parentへのナビゲーションを許可します。このリンクは、1対1関係を実装します。単一の親T-parentが存在します。
-
表T-childからTへの外部キー・リンクごとに、T-childという名前のフィールドを問合せに追加して、TからT-childへのナビゲーションを許可します。このリンクは、1対多関係を実装します。タイプT-childの子が複数存在する場合があります。
中間オブジェクトのネスト解除(フラット化)は、二面性ビューのSQL定義の場合と同じですが、SQLキーワードUNNEST
のかわりに、GraphQLディレクティブ@unnest
を使用します。(ここで示すすべてのGraphQL二面性ビュー定義では、@unnest
を使用します。)
GraphQLでは、ハッシュ/番号記号文字#
が付いた行末コメントを挿入できます。この文字と、同じ行でこれに続く文字はコメントアウトされます。
例3-6 GraphQLを使用した二面性ビューTEAM_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、チーム・オブジェクトには、値がチームのドライバを指定するネストされたオブジェクトの配列であるフィールドdriver
が含まれています。
{"_id" : 301, "name" : "Red Bull", "points" : 0, "driver" : [...]}
(作成されたビューは、例3-1のSQLを使用して作成されたビューと同じです。)
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team @insert @update @delete
{_id : team_id,
name : name,
points : points,
driver : driver @insert @update
[ {driverId : driver_id,
name : name,
points : points @nocheck} ]};
例3-7 GraphQLを使用した二面性ビューDRIVER_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、ドライバ・オブジェクトには、値がフィールドteamId
およびname
を持つネストされたオブジェクトであるフィールドteamInfo
が含まれていません。かわりに、表teamのデータが上位レベルで取り込まれ、チーム名がフィールドteam
となります。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 0,
"teamId" : 103,
"team" : "Red Bull",
"race" : [...]}
ここでは、2つのバージョンのビュー作成を示します。わかりやすくするために、1つ目のバージョンには更新可能性またはETAG計算の除外を宣言する注釈がありません。
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
driver
{_id : driver_id,
name : name,
points : points,
team @unnest
{teamId : team_id,
team : name},
race : driver_race_map
[ {driverRaceMapId : driver_race_map_id,
race @unnest
{raceId : race_id,
name : name},
finalPosition : position} ]};
2つ目のバージョンのビュー作成には、更新可能性およびETAG @nocheck
の注釈があります。(例3-3のSQLを使用して作成されたビューと同じビューが作成されます。)
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
driver @insert @update @delete
{_id : driver_id,
name : name,
points : points,
team @noinsert @noupdate @nodelete
@unnest
{teamId : team_id,
team : name @nocheck},
race : driver_race_map @insert @update @nodelete
[ {driverRaceMapId : driver_race_map_id,
race @noinsert @noupdate @nodelete
@unnest
{raceId : race_id,
name : name},
finalPosition : position} ]};
例3-8 GraphQLを使用した二面性ビューRACE_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、配列result
の要素であるオブジェクトには、値がフィールドdriverId
およびname
を持つネストされたオブジェクトであるフィールドdriverInfo
が含まれていません:
{"driverId" : 103, "name" : "Charles Leclerc", "position" : 1}
ここでは、2つのバージョンのビュー作成を示します。わかりやすくするために、1つ目のバージョンには更新可能性またはETAG計算の除外を宣言する注釈がありません。
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race
{_id : race_id,
name : name,
laps : laps,
date : race_date,
podium : podium,
result : driver_race_map
[ {driverRaceMapId : driver_race_map_id,
position : position,
driver
@unnest
{driverId : driver_id,
name : name}} ]};
2つ目のバージョンのビュー作成には、更新可能性およびETAG @nocheck
の注釈があります。(例3-5のSQLを使用して作成されたビューと同じビューが作成されます。)
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race @insert @update @delete
{_id : race_id,
name : name,
laps : laps @noupdate,
date : race_date,
podium : podium @nocheck,
result : driver_race_map @insert @update @delete
[ {driverRaceMapId : driver_race_map_id,
position : position,
driver @noinsert @update @nodelete
@unnest
{driverId : driver_id,
name : name}} ]};
関連項目:
-
『Oracle Database SQL言語リファレンス』のCREATE JSON RELATIONAL DUALITY VIEWに関する項
親トピック: 二面性ビューの作成
脚注一覧
脚注1: GraphQLで外部キー・リンクを明示的に使用する必要があるのは、2つの表の間に複数の外部キー関係がある場合、または表に同じ表を参照する外部キーがある場合のみです。このような場合は、@link
ディレクティブを使用してリンクを指定します。「JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ」を参照してください。