

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# GraphQL スキーマ
<a name="schema-components"></a>

GraphQL スキーマは GraphQL API の基盤です。データの形状を定義する設計図として機能します。また、データの取得方法や変更方法を定義する、クライアントとサーバー間の契約でもあります。

GraphQL スキーマは *スキーマ定義言語* (SDL) で記述されています。SDL は、構造が確立された型とフィールドで構成されています。
+ **タイプ**: タイプとは、GraphQL がデータの形状と動作を定義する方法です。GraphQL は、このセクションの後半で説明する多数の型をサポートしています。スキーマで定義されている各タイプには、独自のスコープが含まれます。スコープ内には、GraphQL サービスで使用される値またはロジックを含むことができる 1 つ以上のフィールドがあります。型にはさまざまな役割がありますが、最も一般的なのはオブジェクトまたはスカラー (プリミティブ値型) です。
+ **フィールド**: フィールドはタイプのスコープ内に存在し、GraphQL サービスから要求された値を保持します。これらは他のプログラミング言語の変数とよく似ています。フィールドで定義するデータの形状によって、リクエスト/レスポンス操作におけるデータの構造が決まります。これにより、開発者はサービスのバックエンドがどのように実装されているかを知らなくても、何が返されるかを予測できます。

スキーマがどのようなものかを視覚化するために、単純な GraphQL スキーマの内容を確認してみましょう。プロダクションコードでは、スキーマは通常、`schema.graphql` または `schema.json` というファイルにあります。GraphQL サービスを実装するプロジェクトを覗き見していると仮定しましょう。このプロジェクトには会社の人事データが保存されており、`schema.graphql` ファイルを使用して人事データを取得したり、データベースに新しい人員を追加したりしています。コードは次のようになります。

------
#### [ schema.graphql ]

```
type Person {                                  
   id: ID!
   name: String                                  
   age: Int
}
type Query {                                   
  people: [Person]
}
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

------

スキーマには、`Person`、`Query`、`Mutation` の 3 つのタイプが定義されていることがわかります。`Person` を見てみると、これが会社の従業員のインスタンスの設計図であり、それによってこの型がオブジェクトになることが推測できます。そのスコープ内には、`id`、`name`、`age` があります。これらは `Person` のプロパティを定義するフィールドです。つまり、データソースはそれぞれの`Person`の`name`を`String`スカラー (プリミティブ) タイプとして、`age` をスカラー (プリミティブ) タイプとして格納します。`id` はそれぞれの `Person` に対して固有の特別な識別子として機能します。`!` 記号で示されているように、これは必須の値でもあります。

次の 2 つのオブジェクトタイプは動作が異なります。GraphQL は、スキーマへのデータの入力方法を定義する特別なオブジェクトタイプ用にいくつかのキーワードを予約しています。`Query` タイプはソースからデータを取得します。この例では、クエリはデータベースから `Person` オブジェクトを取得する場合があります。これは、RESTful 用語で使われる `GET` 操作を思い起こさせるかもしれません。`Mutation` はデータを変更します. この例では、ミューテーションによってデータベースにさらに `Person` オブジェクトが追加される可能性があります。これにより、`PUT` や `POST` のような状態を変更する操作を思い起こさせるかもしれません。特殊なオブジェクトタイプの動作については、このセクションの後半で説明します。

この例では、`Query` がデータベースから何かを取得すると仮定しましょう。`Query` のフィールドを見ると、`people` というフィールドが 1 つあります。フィールドの値は `[Person]` です。つまり、データベース内の `Person` の一部のインスタンスを取得したいということです。ただし、括弧を追加すると、特定のインスタンスだけでなく、すべての `Person` インスタンスのリストを返したいということになります。

データ変更などの状態を変更する操作は `Mutation` タイプが担当します。ミューテーションは、データソースに対して何らかの状態変更操作を実行する役割を果たします。この例では、データベースに新しい `addPerson` オブジェクトを追加する `Person` という操作がミューテーションに含まれています。このミューテーションは `Person` を使用し、`id`、`name`、`age` フィールドへの入力を期待しています。

この時点で、このような操作は何らかの動作を行い、関数名とパラメータを持つ関数によく似ているはずなのに、コード実装なしで `addPerson` がどのように動作するのか疑問に思われるかもしれません。現在のところ、スキーマは宣言の役割を果たすだけなので、機能しません。`addPerson` の動作を実装するには、リゾルバーを追加する必要があります。リゾルバーは、関連するフィールド (この場合は `addPerson` オペレーション) が呼び出されるたびに実行されるコードの単位です。オペレーションを使いたい場合は、どこかの時点でリゾルバーの実装を追加する必要があります。ある意味では、スキーマ操作は関数宣言、リゾルバーは定義と考えることができます。リゾルバーについては別のセクションで説明します。

この例は、スキーマがデータを操作する最も簡単な方法のみを示しています。GraphQL と AWS AppSyncの機能を活用して、複雑で堅牢でスケーラブルなアプリケーションを構築します。次のセクションでは、スキーマで使用できるさまざまなタイプとフィールドの動作をすべて定義します。

# GraphQL タイプ
<a name="graphql-types"></a>

GraphQL は、さまざまなタイプをサポートします。前のセクションで見たように、タイプはデータの形状や動作を定義します。これらは GraphQL スキーマの基本的な構成要素です。

タイプは入力と出力に分類できます。入力は特殊なオブジェクトタイプ (`Query`、`Mutation` など) の引数として渡すことができるタイプですが、出力タイプはデータの保存と返しにのみ使用されます。タイプとその分類のリストは以下のとおりです。
+ **オブジェクト**: オブジェクトにはエンティティを説明するフィールドが含まれます。例えば、`book`、`authorName`、`publishingYear` などの特性を記述するフィールドを持つオブジェクトのようなものが考えられます。これらは厳密には出力タイプです。
+ **スカラー**: これらは int や string などのプリミティブ型です。通常はフィールドに割り当てられます。`authorName` フィールドを例にとると、「John Smith」のような名前を格納する `String` スカラーを割り当てることができます。スカラーは入力タイプでも出力タイプでもかまいません。
+ **入力**: 入力では、フィールドグループを引数として渡すことができます。オブジェクトとよく似た構造ですが、特別なオブジェクトに引数として渡すことができます。入力を使うと、スカラー、列挙型、その他の入力をスコープ内で定義できます。入力は入力タイプにしかなりません。
+ **特殊オブジェクト**: 特殊オブジェクトは状態を変更する操作を実行し、サービスの面倒な作業の大部分を行います。特殊なオブジェクトタイプには、クエリ、ミューテーション、サブスクリプションの 3 種類があります。通常、クエリはデータを取得し、ミューテーションはデータを操作し、サブスクリプションはクライアントとサーバー間の双方向接続を開いて維持し、常時通信を行います。特殊オブジェクトは、その機能上、入力でも出力でもありません。
+ **列挙型**: 列挙型はあらかじめ定義された有効な値のリストです。列挙型を呼び出す場合、その値はそのスコープで定義されている値のみになります。例えば、交通信号のリストを表すという `trafficLights` がある場合、それには`redLight` や `greenLight` などの値が含まれることがありますが、`purpleLight` にはなり得ません。実際の信号機には信号の数が限られているため、列挙型を使用して信号を定義し、`trafficLight` 参照時にそれらだけが有効な値になるように強制できます。列挙型は入力型でも出力型でもかまいません。
+ **ユニオン/インターフェース**: ユニオンを使うと、クライアントからリクエストされたデータに応じて 1 つ以上のものをリクエストで返すことができます。例えば、`title` フィールドのある `Book` 型と `name` フィールドのある `Author` 型がある場合、両方の型を結合することができます。クライアントが「ジュリアス・シーザー」というフレーズをデータベースから検索したい場合、ユニオンは**ジュリアス・シーザー (ウィリアム・シェイクスピアの戯曲) を `Book` `title` から、**ジュリアス・シーザー(**『コメンタリー・デ・ベロ・ガリコ』の作者) を `Author` `name` から返すことができます。ユニオンは出力タイプとしてのみ使用できます。

  インターフェースは、オブジェクトが実装しなければならないフィールドのセットです。これは、Java などのプログラミング言語のインターフェースに少し似ていますが、インターフェースで定義されたフィールドを実装する必要があります。例えば、`Book``title`フィールドを含むというインターフェースを作成するとします。後で、`Book` を実装したもの `Novel` という型を作成したとします。`Novel` には `title` フィールドを含める必要があります。ただし、`Novel` には、`pageCount` または `ISBN` のような、インターフェイスにない他のフィールドも含めることができます。インターフェースは出力タイプにしかなれません。

以下のセクションでは、各タイプが GraphQL でどのように機能するかを説明します。

## オブジェクト
<a name="object-components"></a>

GraphQL オブジェクトは、プロダクションコードでよく使われるタイプです。GraphQL では、オブジェクトは異なるフィールドの集まりであり (他の言語の変数と同様)、各フィールドは値を保持できる型 (通常はスカラーまたは別のオブジェクト) によって定義されます。オブジェクトは、サービス実装から取得/操作できるデータの単位です。

オブジェクトタイプは `Type` キーワードを使用して宣言されます。スキーマの例を少し変更してみましょう。

```
type Person {
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

ここでのオブジェクトタイプは `Person` と `Occupation` です。各オブジェクトには独自のフィールドと独自のタイプがあります。GraphQL の特徴の 1 つは、フィールドを他のタイプに設定できることです。`Person` の `occupation` フィールドには `Occupation` オブジェクトタイプが含まれていることがわかります。GraphQL はデータを記述するだけで、サービスの実装は記述していないため、この関連付けを行うことができます。

## スカラー
<a name="scalar-components"></a>

スカラーは基本的に、値を保持するプリミティブ型です。には AWS AppSync、デフォルトの GraphQL スカラーとスカラーという 2 AWS AppSync 種類のスカラーがあります。スカラーは通常、オブジェクトタイプ内のフィールド値を格納するために使用されます。GraphQL のデフォルトタイプには `Int`、`Float`、`String`、`Boolean`、`ID` が含まれます。前の例をもう一度使ってみましょう。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

`name` および `title` フィールドを除くと、どちらも `String` スカラーになります。`Name` は "`John Smith`" のような文字列値を返すことができ、タイトルは "`firefighter`" のようなものを返すことができます。一部の GraphQL 実装では、`Scalar` キーワードを使用してタイプの動作を実装するカスタムスカラーもサポートしています。ただし、 AWS AppSync は現時点ではカスタムスカラーを**サポートしていません**。スカラーのリストについては、「[AWS AppSyncのスカラータイプ](https://docs.aws.amazon.com//appsync/latest/devguide/scalars.html)」を参照してください。

## 入力
<a name="input-components"></a>

入力型と出力型の概念により、引数を渡すときには一定の制限があります。一般的に渡す必要がある型、特にオブジェクトには制限があります。入力タイプを使用すると、このルールを回避できます。入力は、スカラー、列挙型、その他の入力タイプを含むタイプです。

入力は `input` キーワードを使用して定義されます。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input personInput { 
  id: ID!
  name: String
  age: Int
  occupation: occupationInput
}

input occupationInput {
  title: String
}
```

ご覧のとおり、元の型を模倣した入力を別々に設定できます。これらの入力は、次のようなフィールド操作でよく使用されます。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

まだ `Occupation` の代わりに `occupationInput` を渡して `Person` を作成することに注意してください。

これは入力の 1 つのシナリオに過ぎません。必ずしもオブジェクトを 1:1 でコピーする必要はありませんし、プロダクションコードでは、このような方法を使用することはほとんどありません。引数として入力する必要があるものだけを定義して、GraphQL スキーマを活用するとよいでしょう。

また、同じ入力を複数の操作で使用することもできますが、これはお勧めしません。スキーマの要件が変更された場合に備えて、各操作には入力の固有のコピーが含まれているのが理想的です。

## 特殊なオブジェクト
<a name="special-object-components"></a>

GraphQL は、スキーマがデータを取得/操作する方法に関するビジネスロジックの一部を定義する特別なオブジェクト用にいくつかのキーワードを予約しています。スキーマには、これらのキーワードがそれぞれ 1 つしか存在できません。これらは、クライアントが GraphQL サービスに対して実行するすべての要求されたデータのエントリポイントとして機能します。

特別なオブジェクトも `type` キーワードを使って定義されます。通常のオブジェクトタイプとは使い方が異なりますが、実装は非常に似ています。

------
#### [ Queries ]

クエリは、読み取り専用のフェッチを実行してソースからデータを取得するという点で `GET` オペレーションとよく似ています。GraphQL では、`Query` がサーバーに対してリクエストを行うクライアントのすべてのエントリポイントを定義します。GraphQL の実装には `Query` が必ずあります。

前のスキーマの例で使用した `Query` と変更されたオブジェクトタイプは次のとおりです。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
type Occupation {
  title: String
}
type Query {                                   
  people: [Person]
}
```

`Query` には、データソースか `Person` インスタンスのリストを返す `people` というフィールドがあります。アプリケーションの動作を変更する必要があり、今度は別の目的で `Occupation` インスタンスのみのリストを返す必要があるとしましょう。これをクエリに追加するだけで済みます。

```
type Query {                                   
  people: [Person]
  occupations: [Occupation]
}
```

GraphQL では、クエリをリクエストの単一ソースとして扱うことができます。お分かりのように、これは、異なるエンドポイントを使用して同じこと (`.../api/1/people` と `.../api/1/occupations`) を実現する RESTful な実装よりもずっと簡単になる可能性があります。

このクエリ用のリゾルバー実装があると仮定すると、実際のクエリを実行できるようになります。`Query` タイプは存在しますが、アプリケーションのコードで実行するには明示的に呼び出す必要があります。これは `query` キーワードを使用して行うことができます。

```
query getItems {
   people {
      name
   }
   occupations {
      title
   }
}
```

ご覧のとおり、このクエリは `getItems` と呼ばれ、`people` (`Person` オブジェクトのリスト) と`occupations` (`Occupation` オブジェクトのリスト) を返します。`people` では、それぞれの `Person` の `name` フィールドのみを返し、それぞれの `Occupation` の `title` フィールドを返しています。また、レスポンスは次のようになります。

```
{
  "data": {
    "people": [
      {
        "name": "John Smith"
      },
      {
        "name": "Andrew Miller"
      },
      .
      .
      .
    ],
    "occupations": [
      {
        "title": "Firefighter"
      },
      {
        "title": "Bookkeeper"
      },
      .
      .
      .
    ]
  }
}
```

レスポンス例は、データがクエリの形状に従っていることを示している。取得された各エントリは、フィールドの範囲内で一覧表示されます。`people` と `occupations`をそれぞれを個別のリストとして返しています。便利ですが、ユーザーの名前と職業のリストを返すようにクエリを変更したほうが便利かもしれません。

```
query getItems {
   people {
      name   
      occupation {
        title
      }
}
```

`Person` タイプには `Occupation` タイプの `occupation` フィールドが含まれているので、これは合法的な変更です。`people` の範囲内にリストされている場合は、`title` によって関連する `Occupation` とともにそれぞれの `Person` の `name` を返すことになります。また、レスポンスは次のようになります。

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "occupation": {
          "title": "Firefighter"
        }
      },
      {
        "name": "Andrew Miller",
        "occupation": {
          "title": "Bookkeeper"
        }
      },
      .
      .
      .
    ]
  }
}
```

------
#### [ Mutations ]

ミューテーションは、`PUT` や `POST` のような状態を変える操作に似ています。書き込み操作を実行してソース内のデータを変更し、レスポンスを取得します。データ変更リクエストのエントリポイントを定義します。クエリとは異なり、ミューテーションはプロジェクトのニーズに応じてスキーマに含まれる場合と含まれない場合があります。スキーマの例からのミューテーションは次のとおりです。

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

`addPerson` フィールドは、`Person` をデータソースに追加する 1 つのエントリポイントを表します。`addPerson` はフィールド名、`id`、`name`、`age` はパラメータ、`Person` は戻り型です。`Person` タイプを振り返ってみます。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
```

`occupation` フィールドを追加しました。ただし、オブジェクトは引数として渡すことができないため、このフィールドを直接 `Occupation` に設定することはできません。オブジェクトは厳密には出力タイプです。代わりに、同じフィールドを含む入力を引数として渡す必要があります。

```
input occupationInput {
  title: String
}
```

 新しいインスタンスを作るときに、パラメータとして含めるように簡単に `addPerson` を更新することもできます。

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

更新されたスキーマは次のとおりです。

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

元のオブジェクトの代わりに、`occupation` が `occupationInput` から `title` フィールドに渡すことで `Person` の作成が完了することに注意してください。`addPerson` のリゾルバーの実装があると仮定すると、実際のミューテーションを実行できるようになりました。`Mutation` 型は存在しますが、アプリケーションのコードで実行するには明示的に呼び出す必要があります。これは `mutation` キーワードを使用して行うことができます。

```
mutation createPerson {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput) {
    name
    age
    occupation {
      title
    }
  }
}
```

このミューテーションは `createPerson` と呼ばれ、`addPerson` がオペレーションです。新しい `Person` を作成するには `id`、`name`、`age`、`occupation` の引数を入力します。`addPerson` の範囲には、`name`、`age` などの他のフィールドもあります。これはあなたのレスポンスです。これらは `addPerson` オペレーションが完了した後に返されるフィールドです。この例の最後の部分は次のとおりです。

```
mutation createPerson {
  addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner") {
    id
    name
    age
    occupation {
      title
    }
  }
}
```

このミューテーションを使用すると、結果は以下のようになります。

```
{
  "data": {
    "addPerson": {
      "id": "1",
      "name": "Steve Powers",
      "age": "50",
      "occupation": {
        "title": "Miner"
      }
    }
  }
}
```

ご覧のとおり、レスポンスはリクエストした値を、ミューテーションで定義したのと同じ形式で返しました。混乱を減らし、今後さらにクエリが必要にならないように、変更されたすべての値を返すことをお勧めします。ミューテーションを使うと、複数の操作をその範囲に含めることができます。これらはミューテーションにリストされている順序で順番に実行されます。例えば、データソースに役職を追加する `addOccupation` という操作をもう 1 つ作成した場合、これを `addPerson` の後にミューテーションで呼び出すことができます。`addPerson` が最初に処理され、その後に `addOccupation` が処理されます。

------
#### [ Subscriptions ]

サブスクリプションは [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications) を使用して、サーバーとクライアント間の永続的な双方向接続を開きます。通常、クライアントはサーバーをサブスクライブまたはリッスンします。サーバーがサーバー側で変更を加えたり、イベントを実行したりするたびに、サブスクライブしているクライアントは更新を受け取ります。このタイプのプロトコルは、複数のクライアントがサブスクライブしていて、サーバーや他のクライアントで発生した変更について通知を受ける必要がある場合に役立ちます。例えば、サブスクリプションを使用してソーシャルメディアフィードを更新できます。ユーザー A とユーザー B の 2 人のユーザーが、どちらもダイレクトメッセージを受信するたびに自動通知更新をサブスクライブしている場合があります。クライアント A のユーザー A は、クライアント B のユーザー B にダイレクトメッセージを送信できます。ユーザー A のクライアントはダイレクトメッセージを送信し、サーバーによって処理されます。その後、サーバーはユーザー B のアカウントにダイレクトメッセージを送信し、クライアント B には自動通知を送信します。

スキーマの例に追加できる `Subscription` の例を以下に示します。

```
type Subscription {                                   
  personAdded: Person
}
```

`personAdded` フィールドは、データソースに新しい `Person` が追加されるたびに、サブスクライブしているクライアントにメッセージを送信します。`personAdded` のリゾルバーの実装があると仮定すると、サブスクリプションを使用できるようになりました。`Subscription` 型は存在しますが、アプリケーションのコード内で実行するには明示的に呼び出す必要があります。これは `subscription` キーワードを使用して行うことができます。

```
subscription personAddedOperation {
  personAdded {
    id
    name
  }
}
```

サブスクリプションは `personAddedOperation` と呼ばれ、オペレーションは `personAdded` です。`personAdded` は新しい `Person` インスタンスの `id` および `name` フィールドを返します。ミューテーションの例を見てみると、以下の操作を使用して `Person` を追加しました。

```
addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner")
```

クライアントが新しく追加された `Person` へのアップデートを購読していた場合、`addPerson` 実行後に以下のように表示されるかもしれません。

```
{
  "data": {
    "personAdded": {
      "id": "1",
      "name": "Steve Powers"
    }
  }
}
```

以下は、サブスクリプションが提供するものの概要です。

サブスクリプションは、クライアントとサーバーが迅速で安定したアップデートを受信できるようにする双方向のチャネルです。通常、標準化された安全な接続を実現する WebSocket プロトコルを使用します。

サブスクリプションは、接続設定のオーバーヘッドを減らすという点で機敏です。一度サブスクライブすると、クライアントはそのサブスクリプションで長期間稼働し続けることができます。通常、開発者がサブスクリプションの有効期間を調整したり、要求される情報を設定したりできるようにすることで、コンピューティングリソースを効率的に使用します。

一般に、サブスクリプションを使用すると、クライアントは一度に複数のサブスクリプションを作成できます。サブスクリプションは AWS AppSync、 AWS AppSync サービスからのリアルタイム更新の受信にのみ使用されます。クエリやミューテーションの実行には使用できません。

サブスクリプションに代わる主な方法はポーリングです。ポーリングでは、設定した間隔でクエリを送信してデータを要求します。このプロセスは通常、サブスクリプションほど効率的ではなく、クライアントとバックエンドの両方に大きな負担をかけます。

------

スキーマの例では言及されていなかったことの 1 つは、特殊なオブジェクト型も `schema` ルートで定義しなければならないという事実です。したがって、スキーマをエクスポートすると AWS AppSync、次のようになります。

------
#### [ schema.graphql ]

```
schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}

.
.
.

type Query {                                   
  # code goes here
}
type Mutation {                                   
  # code goes here
}
type Subscription {                                   
  # code goes here
}
```

------

## 列挙型
<a name="enum-components"></a>

列挙型は、タイプやフィールドが持つ可能性のある有効な引数を制限する特殊なスカラーです。つまり、スキーマで列挙型が定義されると、それに関連するタイプまたはフィールドは列挙型内の値に限定されます。列挙型は文字列スカラーとしてシリアル化されます。プログラミング言語が異なれば、GraphQL 列挙型の処理も異なる場合があることに注意してください。例えば、JavaScript はネイティブの列挙型をサポートしていないため、代わりに列挙値を int 値にマップできます。

列挙型は `enum` キーワードを使用して定義されます。例を示します。

```
enum trafficSignals {
  solidRed
  solidYellow
  solidGreen
  greenArrowLeft
  ...
}
```

`trafficLights` 列挙型を呼び出すとき、引数に指定できるのは `solidRed`、`solidYellow`、`solidGreen` などのみです。列挙型を使うのは、はっきりしているが選択肢の数が限られているものを表すのに使うのが一般的です。

## ユニオン/インターフェース
<a name="union-interface-components"></a>

GraphQL の「[Interface と Union](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html)」を参照してください。

# GraphQL フィールド
<a name="graphql-fields"></a>

フィールドはタイプのスコープ内に存在し、GraphQL サービスから要求された値を保持します。これらは、他のプログラミング言語の変数とよく似ています。例えば、次のような `Person` オブジェクトタイプがあります。

```
type Person {                                  
   name: String                                  
   age: Int
}
```

この場合のフィールドはそれぞれ `name` `age` で、`String` および `Int` 値が格納されます。上に示したようなオブジェクトフィールドは、クエリやミューテーションのフィールド (オペレーション) の入力として使用できます。例については、以下の `Query` を参照してください

```
type Query {                                   
  people: [Person]
}
```

`people` フィールドは、データソースから `Person` のすべてのインスタンスを要求しています。GraphQL サーバーで `Person` を追加または取得すると、データはタイプとフィールドの形式に従うことが期待できます。つまり、スキーマ内のデータの構造によって、レスポンスでどのように構造化されるかが決まります。

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "age": "50"
      },
      {
        "name": "Andrew Miller",
        "age": "60"
      },
      .
      .
      .
    ]
  }
}
```

フィールドはデータを構造化する上で重要な役割を果たします。以下で説明するように、フィールドに適用してさらにカスタマイズできるプロパティがいくつかあります。

## Lists
<a name="list-components"></a>

リストは指定されたタイプのすべての項目を返します。リストは括弧 `[]` を使ってフィールドの型に追加できます。

```
type Person { 
  name: String
  age: Int
}
type Query {                                   
  people: [Person]
}
```

`Query` では、`Person` を囲んでいる括弧は、データソースからの `Person` のすべてのインスタンスを配列として返したいことを示しています。レスポンスでは、それぞれの `Person`の `name` および `age` の値が 1 つの区切りリストとして返されます。

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",         # Data of Person 1
        "age": "50"
      },
      {
        "name": "Andrew Miller",      # Data of Person 2
        "age": "60"
      },
      .                               # Data of Person N
      .
      .
    ]
  }
}
```

使用できるのは特殊なオブジェクトタイプだけではありません。リストは通常のオブジェクトタイプのフィールドでも使用できます。

## NULL 以外
<a name="non-null-components"></a>

NULL 以外は、レスポンスで NULL であってはならないフィールドを示します。`!` 記号を使用して、フィールドを NULL 以外に設定できます。

```
type Person { 
  name: String!
  age: Int
}
type Query {                                   
  people: [Person]
}
```

`name` フィールドを明示的に NULL にすることはできません。データソースにクエリを実行して、このフィールドに NULL を入力すると、エラーが発生します。

リストと NULL 以外を組み合わせることができます。次のクエリを比較してください。

```
type Query {                                   
  people: [Person!]      # Use case 1
}

.
.
.

type Query {                                   
  people: [Person]!      # Use case 2
}

.
.
.

type Query {                                   
  people: [Person!]!     # Use case 3
}
```

ユースケース 1 では、リストに NULL 項目を含めることはできません。ユースケース 2 では、リスト自体を NULL に設定することはできません。ユースケース 3 では、リストとその項目を NULL にすることはできません。ただし、いずれにしても、空のリストを返すことはできます。

ご覧のとおり、GraphQL には動くコンポーネントがたくさんあります。このセクションでは、単純なスキーマの構造と、スキーマがサポートするさまざまなタイプとフィールドを示しました。次のセクションでは、GraphQL API の他のコンポーネントと、それらがスキーマとどのように連携するかを説明します。