

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# GraphQL-Schemas
<a name="schema-components"></a>

Das GraphQL-Schema ist die Grundlage einer GraphQL-API. Es dient als Blaupause, die die Form Ihrer Daten definiert. Es ist auch ein Vertrag zwischen Ihrem Client und Ihrem Server, der festlegt, wie Ihre Daten abgerufen und and/or geändert werden.

GraphQL-Schemas sind in der *Schema Definition Language* (SDL) geschrieben. SDL besteht aus Typen und Feldern mit einer etablierten Struktur:
+ **Typen**: Mit Typen definiert GraphQL die Form und das Verhalten der Daten. GraphQL unterstützt eine Vielzahl von Typen, die später in diesem Abschnitt erklärt werden. Jeder Typ, der in Ihrem Schema definiert ist, enthält seinen eigenen Bereich. Innerhalb des Bereichs befinden sich ein oder mehrere Felder, die einen Wert oder eine Logik enthalten können, die in Ihrem GraphQL-Dienst verwendet werden. Typen erfüllen viele verschiedene Rollen, am häufigsten sind Objekte oder Skalare (primitive Werttypen).
+ **Felder**: Felder existieren innerhalb des Gültigkeitsbereichs eines Typs und enthalten den Wert, der vom GraphQL-Dienst angefordert wird. Diese sind Variablen in anderen Programmiersprachen sehr ähnlich. Die Form der Daten, die Sie in Ihren Feldern definieren, bestimmt, wie die Daten in einer request/response Operation strukturiert werden. Auf diese Weise können Entwickler vorhersagen, was zurückgegeben wird, ohne zu wissen, wie das Backend des Dienstes implementiert ist.

Um zu visualisieren, wie ein Schema aussehen würde, schauen wir uns den Inhalt eines einfachen GraphQL-Schemas an. Im Produktionscode befindet sich Ihr Schema normalerweise in einer Datei namens `schema.graphql` oder`schema.json`. Nehmen wir an, wir schauen uns ein Projekt an, das einen GraphQL-Dienst implementiert. In diesem Projekt werden Personaldaten des Unternehmens gespeichert, und die `schema.graphql` Datei wird verwendet, um Personaldaten abzurufen und neues Personal zu einer Datenbank hinzuzufügen. Der Code könnte so aussehen:

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

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

------

Wir können sehen, dass im Schema drei Typen definiert sind: `Person``Query`, und`Mutation`. Wenn wir uns das ansehen`Person`, können wir vermuten, dass dies die Blaupause für eine Instanz eines Unternehmensmitarbeiters ist, was diesen Typ zu einem Objekt machen würde. In seinem Geltungsbereich sehen wir, `id``name`, und`age`. Dies sind die Felder, die die Eigenschaften von a definieren`Person`. Das bedeutet, dass unsere Datenquelle jeden `Person` Typ `name` als `String` skalaren (primitiven) Typ und `age` als `Int` skalaren (primitiven) Typ speichert. Der `id` fungiert als besonderer, eindeutiger Bezeichner für jeden. `Person` Es ist auch ein erforderlicher Wert, wie durch das `!` Symbol gekennzeichnet.

Die nächsten beiden Objekttypen verhalten sich unterschiedlich. GraphQL reserviert einige Schlüsselwörter für spezielle Objekttypen, die definieren, wie die Daten im Schema aufgefüllt werden. Ein `Query` Typ ruft Daten aus der Quelle ab. In unserem Beispiel könnte unsere Abfrage `Person` Objekte aus einer Datenbank abrufen. Dies erinnert Sie möglicherweise an `GET` Operationen in der RESTful Terminologie. A `Mutation` wird Daten ändern. In unserem Beispiel kann unsere Mutation der Datenbank weitere `Person` Objekte hinzufügen. Das erinnert Sie vielleicht an Operationen zur Änderung des Zustands wie `PUT` oder`POST`. Das Verhalten aller speziellen Objekttypen wird später in diesem Abschnitt erklärt.

Nehmen wir an, dass `Query` in unserem Beispiel etwas aus der Datenbank abgerufen wird. Wenn wir uns die Felder von ansehen`Query`, sehen wir ein Feld namens`people`. Sein Feldwert ist`[Person]`. Das bedeutet, dass wir eine Instanz von `Person` in der Datenbank abrufen möchten. Das Hinzufügen von Klammern bedeutet jedoch, dass wir eine Liste aller `Person` Instanzen zurückgeben möchten und nicht nur eine bestimmte.

Der `Mutation` Typ ist für die Ausführung von Zustandsänderungsoperationen wie Datenänderungen verantwortlich. Eine Mutation ist dafür verantwortlich, dass eine Operation zur Änderung des Zustands an der Datenquelle ausgeführt wird. In unserem Beispiel enthält unsere Mutation eine aufgerufene Operation`addPerson`, die der Datenbank ein neues `Person` Objekt hinzufügt. Die Mutation verwendet ein `Person` und erwartet eine Eingabe für die `age` Felder `id``name`, und.

An dieser Stelle wundern Sie sich vielleicht, wie Operationen wie ohne eine Code-Implementierung `addPerson` funktionieren, da sie angeblich ein gewisses Verhalten ausführt und einer Funktion mit einem Funktionsnamen und Parametern sehr ähnlich sieht. Derzeit funktioniert es nicht, da ein Schema nur als Deklaration dient. Um das Verhalten von zu implementieren`addPerson`, müssten wir ihm einen Resolver hinzufügen. Ein Resolver ist eine Codeeinheit, die immer dann ausgeführt wird, wenn das zugehörige Feld (in diesem Fall die `addPerson` Operation) aufgerufen wird. Wenn Sie eine Operation verwenden möchten, müssen Sie die Resolver-Implementierung irgendwann hinzufügen. In gewisser Weise können Sie sich die Schemaoperation als Funktionsdeklaration und den Resolver als Definition vorstellen. Resolver werden in einem anderen Abschnitt erklärt.

Dieses Beispiel zeigt nur die einfachsten Möglichkeiten, wie ein Schema Daten manipulieren kann. Sie erstellen komplexe, robuste und skalierbare Anwendungen, indem Sie die Funktionen von GraphQL nutzen und. AWS AppSync Im nächsten Abschnitt definieren wir all die verschiedenen Typen und Feldverhalten, die Sie in Ihrem Schema verwenden können.

# GraphQL-Typen
<a name="graphql-types"></a>

GraphQL unterstützt viele verschiedene Typen. Wie Sie im vorherigen Abschnitt gesehen haben, definieren Typen die Form oder das Verhalten Ihrer Daten. Sie sind die grundlegenden Bausteine eines GraphQL-Schemas. 

Typen können in Eingaben und Ausgaben eingeteilt werden. Eingaben sind Typen, die als Argument für die speziellen Objekttypen (`Query`, usw.) übergeben werden dürfen`Mutation`, wohingegen Ausgabetypen ausschließlich zum Speichern und Zurückgeben von Daten verwendet werden. Eine Liste der Typen und ihrer Kategorisierungen ist unten aufgeführt:
+ **Objekte**: Ein Objekt enthält Felder, die eine Entität beschreiben. Zum Beispiel könnte ein Objekt so etwas wie ein sein, `book` mit Feldern, die seine Eigenschaften beschreiben `authorName``publishingYear`, wie, usw. Es handelt sich ausschließlich um Ausgabetypen.
+ **Skalare**: Dies sind primitive Typen wie int, string usw. Sie werden normalerweise Feldern zugewiesen. Anhand des `authorName` Felds als Beispiel könnte ihm der `String` Skalar zugewiesen werden, um einen Namen wie „John Smith“ zu speichern. Skalare können sowohl Eingabe- als auch Ausgabetypen sein.
+ **Eingaben**: Eingaben ermöglichen es Ihnen, eine Gruppe von Feldern als Argument zu übergeben. Sie sind sehr ähnlich strukturiert wie Objekte, können aber als Argumente an spezielle Objekte übergeben werden. Mithilfe von Eingaben können Sie Skalare, Aufzählungen und andere Eingaben in ihrem Gültigkeitsbereich definieren. Eingaben können nur Eingabetypen sein.
+ **Spezialobjekte**: Spezielle Objekte führen zustandsverändernde Operationen durch und übernehmen den Großteil der Schwerstarbeit des Dienstes. Es gibt drei spezielle Objekttypen: Abfrage, Mutation und Abonnement. Abfragen rufen in der Regel Daten ab; Mutationen manipulieren Daten; Abonnements öffnen und halten eine bidirektionale Verbindung zwischen Clients und Servern aufrecht, sodass eine ständige Kommunikation gewährleistet ist. Spezielle Objekte können aufgrund ihrer Funktionalität weder eingegeben noch ausgegeben werden.
+ **Enums**: Enums sind vordefinierte Listen zulässiger Werte. Wenn Sie eine Aufzählung aufrufen, können ihre Werte nur den Werten entsprechen, die in ihrem Gültigkeitsbereich definiert sind. Wenn Sie beispielsweise eine Aufzählung mit dem Namen „`trafficLights`Darstellung einer Liste von Verkehrssignalen“ haben, könnte sie Werte wie `redLight` und `greenLight` aber nicht haben. `purpleLight` Eine echte Ampel hat nur eine begrenzte Anzahl von Signalen, sodass Sie diese anhand der Aufzählung definieren und sie bei der Referenzierung als einzig zulässige Werte erzwingen könnten. `trafficLight` Aufzählungen können sowohl Eingabe- als auch Ausgabetypen sein.
+ **Unions/Interfaces**: Unions ermöglichen es Ihnen, ein oder mehrere Dinge in einer Anfrage zurückzugeben, abhängig von den Daten, die vom Client angefordert wurden. Wenn Sie beispielsweise einen Typ mit einem `title` Feld und einen `Book` Typ mit einem Feld hätten, könnten Sie eine `name` Vereinigung zwischen beiden `Author` Typen erstellen. Wenn Ihr Kunde eine Datenbank nach dem Ausdruck „Julius Caesar“ abfragen möchte, könnte die Vereinigung *Julius Caesar* (das Stück von William Shakespeare) aus dem `Book` `title` und *Julius Caesar* (den Autor von *Commentarii de* Bello Gallico) aus dem zurückgeben. `Author` `name` Unions können nur Ausgabetypen sein.

  Schnittstellen sind Gruppen von Feldern, die Objekte implementieren müssen. Dies ist ein bisschen vergleichbar mit Schnittstellen in Programmiersprachen wie Java, wo Sie die in der Schnittstelle definierten Felder implementieren müssen. Nehmen wir zum Beispiel an, Sie haben eine Schnittstelle namens erstellt`Book`, die ein `title` Feld enthält. Nehmen wir an, Sie haben später einen Typ namens `Novel` Implemented erstellt`Book`. Sie `Novel` müssten ein `title` Feld einschließen. Sie `Novel` könnten jedoch auch andere Felder hinzufügen, die nicht in der Benutzeroberfläche enthalten sind, wie `pageCount` oder`ISBN`. Schnittstellen können nur Ausgabetypen sein.

In den folgenden Abschnitten wird erklärt, wie die einzelnen Typen in GraphQL funktionieren.

## Objekte
<a name="object-components"></a>

GraphQL-Objekte sind der Haupttyp, den Sie im Produktionscode sehen werden. In GraphQL können Sie sich ein Objekt als eine Gruppierung verschiedener Felder vorstellen (ähnlich wie Variablen in anderen Sprachen), wobei jedes Feld durch einen Typ (normalerweise ein Skalar oder ein anderes Objekt) definiert wird, der einen Wert enthalten kann. Objekte stellen eine Dateneinheit dar, die retrieved/manipulated aus Ihrer Service-Implementierung stammen kann.

Objekttypen werden mit dem `Type` Schlüsselwort deklariert. Lassen Sie uns unser Schemabeispiel leicht modifizieren:

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

type Occupation {
  title: String
}
```

Die Objekttypen hier sind `Person` und`Occupation`. Jedes Objekt hat seine eigenen Felder mit eigenen Typen. Eine Funktion von GraphQL ist die Möglichkeit, Felder auf andere Typen festzulegen. Sie können sehen, dass das `occupation` Feld in einen `Occupation` Objekttyp `Person` enthält. Wir können diese Assoziation herstellen, weil GraphQL nur die Daten beschreibt und nicht die Implementierung des Dienstes.

## Skalare
<a name="scalar-components"></a>

Skalare sind im Wesentlichen primitive Typen, die Werte enthalten. In gibt AWS AppSync es zwei Arten von Skalaren: die standardmäßigen GraphQL-Skalare und Skalare. AWS AppSync Skalare werden normalerweise verwendet, um Feldwerte innerhalb von Objekttypen zu speichern. Zu den standardmäßigen GraphQL-Typen gehören `Int``Float`,`String`,`Boolean`, und`ID`. Lassen Sie uns das vorherige Beispiel noch einmal verwenden:

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

type Occupation {
  title: String
}
```

Wenn wir die `title` Felder `name` und herausgreifen, enthalten beide einen `String` Skalar. `Name`könnte einen Zeichenkettenwert wie "`John Smith`" zurückgeben und der Titel könnte etwas wie "" `firefighter` zurückgeben. Einige GraphQL-Implementierungen unterstützen auch benutzerdefinierte Skalare, die das `Scalar` Schlüsselwort verwenden und das Verhalten des Typs implementieren. **Unterstützt AWS AppSync derzeit jedoch keine benutzerdefinierten Skalare**. Eine Liste der Skalare finden Sie unter [Skalartypen](https://docs.aws.amazon.com//appsync/latest/devguide/scalars.html) in. AWS AppSync

## Eingaben
<a name="input-components"></a>

Aufgrund des Konzepts der Eingabe- und Ausgabetypen gelten bestimmte Einschränkungen bei der Übergabe von Argumenten. Typen, die üblicherweise übergeben werden müssen, insbesondere Objekte, sind eingeschränkt. Sie können den Eingabetyp verwenden, um diese Regel zu umgehen. Eingaben sind Typen, die Skalare, Aufzählungen und andere Eingabetypen enthalten.

Eingaben werden mit dem Schlüsselwort definiert: `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
}
```

Wie Sie sehen können, können wir separate Eingaben haben, die den ursprünglichen Typ nachahmen. Diese Eingaben werden häufig in Ihren Feldoperationen wie folgt verwendet:

```
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
}
```

Beachten Sie, dass wir immer noch übergeben`occupationInput`, anstatt eine `Occupation` zu erstellen`Person`. 

Dies ist nur ein Szenario für Eingaben. Sie müssen Objekte nicht unbedingt 1:1 kopieren, und im Produktionscode werden Sie ihn höchstwahrscheinlich nicht so verwenden. Es empfiehlt sich, GraphQL-Schemas zu nutzen, indem Sie nur das definieren, was Sie als Argumente eingeben müssen.

Dieselben Eingaben können auch in mehreren Operationen verwendet werden, aber wir empfehlen, dies nicht zu tun. Jede Operation sollte idealerweise eine eigene eindeutige Kopie der Eingaben enthalten, falls sich die Anforderungen des Schemas ändern.

## Besondere Objekte
<a name="special-object-components"></a>

GraphQL reserviert einige Schlüsselwörter für spezielle Objekte, die einen Teil der Geschäftslogik dafür definieren, wie Ihr Schema retrieve/manipulate Daten verarbeitet. In einem Schema kann höchstens eines dieser Schlüsselwörter vorkommen. Sie dienen als Einstiegspunkte für alle angeforderten Daten, die Ihre Clients für Ihren GraphQL-Dienst ausführen. 

Spezielle Objekte werden ebenfalls mit dem `type` Schlüsselwort definiert. Obwohl sie anders als normale Objekttypen verwendet werden, ist ihre Implementierung sehr ähnlich.

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

Abfragen sind `GET` Operationen insofern sehr ähnlich, als sie einen schreibgeschützten Abruf durchführen, um Daten aus Ihrer Quelle abzurufen. In GraphQL `Query` definiert der alle Einstiegspunkte für Clients, die Anfragen an Ihren Server stellen. In Ihrer GraphQL-Implementierung wird es immer eine `Query` geben.

Hier sind die `Query` und die modifizierten Objekttypen, die wir in unserem vorherigen Schemabeispiel verwendet haben:

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

Unser `Query` enthält ein Feld namens`people`, das eine Liste von `Person` Instanzen aus der Datenquelle zurückgibt. Nehmen wir an, wir müssen das Verhalten unserer Anwendung ändern, und jetzt müssen wir eine Liste nur der `Occupation` Instanzen für einen bestimmten Zweck zurückgeben. Wir könnten es einfach zur Abfrage hinzufügen:

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

In GraphQL können wir unsere Abfrage als einzige Quelle für Anfragen behandeln. Wie Sie sehen können, ist dies potenziell viel einfacher als RESTful Implementierungen, die möglicherweise unterschiedliche Endpunkte verwenden, um dasselbe zu erreichen (`.../api/1/people`und). `.../api/1/occupations`

Angenommen, wir haben eine Resolver-Implementierung für diese Abfrage, können wir jetzt eine tatsächliche Abfrage durchführen. Obwohl der `Query` Typ existiert, müssen wir ihn explizit aufrufen, damit er im Code der Anwendung ausgeführt werden kann. Dies kann mit dem `query` Schlüsselwort geschehen:

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

Wie Sie sehen können, wird diese Abfrage aufgerufen `getItems` und gibt `people` (eine Liste von `Person` Objekten) und `occupations` (eine Liste von `Occupation` Objekten) zurück. `people`In geben wir nur das `name` Feld von jedem zurück`Person`, während wir jeweils das `title` Feld zurückgeben`Occupation`. Die Antwort könnte so aussehen:

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

Die Beispielantwort zeigt, wie die Daten der Form der Abfrage folgen. Jeder abgerufene Eintrag wird im Bereich des Felds aufgeführt. `people`und geben `occupations` Dinge als separate Listen zurück. Obwohl nützlich, könnte es bequemer sein, die Abfrage so zu ändern, dass sie eine Liste mit Namen und Berufen von Personen zurückgibt:

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

Dies ist eine legale Änderung, da unser `Person` Typ ein `occupation` Feld vom Typ `Occupation` enthält. Wenn es im Geltungsbereich von aufgeführt `Person` ist`people`, geben wir jedes Feld `name` zusammen mit dem zugehörigen Wert `Occupation` von zurück`title`. Die Antwort könnte so aussehen:

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

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

Mutationen ähneln zustandsverändernden Operationen wie `PUT` oder`POST`. Sie führen einen Schreibvorgang durch, um Daten in der Quelle zu ändern, und rufen dann die Antwort ab. Sie definieren Ihre Einstiegspunkte für Anfragen zur Datenänderung. Im Gegensatz zu Abfragen kann eine Mutation je nach den Anforderungen des Projekts in das Schema aufgenommen werden oder auch nicht. Hier ist die Mutation aus dem Schemabeispiel:

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

Das `addPerson` Feld stellt einen Einstiegspunkt dar, der der Datenquelle a `Person` hinzufügt. `addPerson`ist der Feldname;`id`,`name`, und `age` sind die Parameter; und `Person` ist der Rückgabetyp. Rückblick auf den `Person` Typ:

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

Wir haben das `occupation` Feld hinzugefügt. Wir können dieses Feld jedoch nicht `Occupation` direkt auf setzen, da Objekte nicht als Argumente übergeben werden können; es handelt sich ausschließlich um Ausgabetypen. Wir sollten stattdessen eine Eingabe mit denselben Feldern als Argument übergeben:

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

 Wir können unsere auch einfach aktualisieren`addPerson`, um dies als Parameter einzubeziehen, wenn wir neue `Person` Instanzen erstellen:

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

Hier ist das aktualisierte Schema:

```
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
}
```

Beachten Sie, dass das `title` Feld von übergeben `occupation` wird`occupationInput`, um die Erstellung des Objekts `Person` anstelle des ursprünglichen `Occupation` Objekts abzuschließen. Unter der Annahme, dass wir eine Resolver-Implementierung für haben`addPerson`, können wir jetzt eine tatsächliche Mutation durchführen. Obwohl der `Mutation` Typ existiert, müssen wir ihn explizit aufrufen, damit er im Code der Anwendung ausgeführt wird. Dies kann mit dem `mutation` Schlüsselwort geschehen:

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

Diese Mutation wird als Operation bezeichnet `createPerson` und `addPerson` ist die Operation. Um eine neue zu erstellen`Person`, können wir die Argumente für`id`, `name``age`, und eingeben`occupation`. Im Rahmen von `addPerson` können wir auch andere Felder wie `name``age`, usw. sehen. Dies ist Ihre Antwort. Dies sind die Felder, die nach Abschluss des `addPerson` Vorgangs zurückgegeben werden. Hier ist der letzte Teil des Beispiels:

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

Mit dieser Mutation könnte ein Ergebnis so aussehen:

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

Wie Sie sehen können, hat die Antwort die von uns angeforderten Werte in demselben Format zurückgegeben, das in unserer Mutation definiert war. Es empfiehlt sich, alle Werte zurückzugeben, die geändert wurden, um Verwirrung zu vermeiden und die Notwendigkeit weiterer Abfragen in der future zu verringern. Mutationen ermöglichen es Ihnen, mehrere Operationen in ihren Geltungsbereich einzubeziehen. Sie werden nacheinander in der Reihenfolge ausgeführt, die in der Mutation angegeben ist. Wenn wir beispielsweise eine weitere Operation mit dem Namen erstellen`addOccupation`, die Berufsbezeichnungen zur Datenquelle hinzufügt, können wir dies in der nachfolgenden Mutation aufrufen. `addPerson` `addPerson`wird zuerst bearbeitet, gefolgt von`addOccupation`.

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

Abonnements dienen [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications)dazu, eine dauerhafte bidirektionale Verbindung zwischen dem Server und seinen Clients herzustellen. In der Regel abonniert ein Client den Server oder hört ihn ab. Immer wenn der Server eine serverseitige Änderung vornimmt oder ein Ereignis ausführt, erhält der abonnierte Client die Updates. Dieser Protokolltyp ist nützlich, wenn mehrere Clients abonniert sind und über Änderungen auf dem Server oder anderen Clients informiert werden müssen. Abonnements können beispielsweise verwendet werden, um Social-Media-Feeds zu aktualisieren. Es könnte zwei Benutzer geben, Benutzer A und Benutzer B, die beide automatische Benachrichtigungen abonniert haben, wenn sie Direktnachrichten erhalten. Benutzer A auf Client A könnte eine Direktnachricht an Benutzer B auf Client B senden. Der Client von Benutzer A würde die Direktnachricht senden, die vom Server verarbeitet würde. Der Server würde dann die Direktnachricht an das Konto von Benutzer B senden und gleichzeitig eine automatische Benachrichtigung an Client B senden.

Hier ist ein Beispiel für a`Subscription`, das wir dem Schemabeispiel hinzufügen könnten:

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

Das `personAdded` Feld sendet eine Nachricht an abonnierte Kunden, wenn der Datenquelle eine neue hinzugefügt `Person` wird. Vorausgesetzt, wir haben eine Resolver-Implementierung für`personAdded`, können wir jetzt das Abonnement verwenden. Obwohl der `Subscription` Typ existiert, müssen wir ihn explizit aufrufen, damit er im Code der Anwendung ausgeführt wird. Dies kann mit dem `subscription` Schlüsselwort geschehen:

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

Das Abonnement wird aufgerufen`personAddedOperation`, und der Vorgang ist`personAdded`. `personAdded`gibt die `name` Felder `id` und und neuer `Person` Instanzen zurück. Wenn wir uns das Mutationsbeispiel ansehen, haben wir `Person` mit dieser Operation eine hinzugefügt:

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

Wenn unsere Kunden Updates für die neu hinzugefügten Apps abonniert hätten`Person`, könnten sie nach dem Start Folgendes sehen`addPerson`:

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

Im Folgenden finden Sie eine Zusammenfassung dessen, was Abonnements bieten:

Abonnements sind bidirektionale Kanäle, die es dem Client und dem Server ermöglichen, schnelle, aber stetige Updates zu erhalten. Sie verwenden in der Regel das WebSocket Protokoll, das standardisierte und sichere Verbindungen herstellt.

Abonnements sind insofern flexibel, als sie den Aufwand für den Verbindungsaufbau reduzieren. Einmal abonniert, kann ein Kunde dieses Abonnement einfach über einen längeren Zeitraum nutzen. Sie nutzen Computerressourcen in der Regel effizient, indem sie es Entwicklern ermöglichen, die Laufzeit des Abonnements individuell zu gestalten und zu konfigurieren, welche Informationen angefordert werden.

Im Allgemeinen ermöglichen Abonnements dem Kunden, mehrere Abonnements gleichzeitig abzuschließen. Apropos AWS AppSync, Abonnements werden nur für den Empfang von Echtzeit-Updates vom AWS AppSync Dienst verwendet. Sie können nicht zur Durchführung von Abfragen oder Mutationen verwendet werden.

Die wichtigste Alternative zu Abonnements ist das Polling, bei dem Abfragen in festgelegten Intervallen gesendet werden, um Daten anzufordern. Dieser Prozess ist in der Regel weniger effizient als Abonnements und belastet sowohl den Client als auch das Backend stark.

------

Eine Sache, die in unserem Schemabeispiel nicht erwähnt wurde, war die Tatsache, dass Ihre speziellen Objekttypen auch in einem `schema` Root-Verzeichnis definiert werden müssen. Wenn Sie also ein Schema exportieren AWS AppSync, könnte es so aussehen:

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

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

.
.
.

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

------

## Aufzählungen
<a name="enum-components"></a>

Aufzählungen oder Aufzählungen sind spezielle Skalare, die die zulässigen Argumente einschränken, die ein Typ oder Feld haben kann. Das bedeutet, dass immer dann, wenn eine Aufzählung im Schema definiert wird, der zugehörige Typ oder das zugehörige Feld auf die Werte in der Aufzählung beschränkt wird. Aufzählungen werden als Zeichenkettenskalare serialisiert. Beachten Sie, dass verschiedene Programmiersprachen GraphQL-Enums möglicherweise unterschiedlich handhaben. JavaScript Hat beispielsweise keine native Enum-Unterstützung, sodass die Enum-Werte stattdessen Int-Werten zugeordnet werden können.

Aufzählungen werden mit dem Schlüsselwort definiert. `enum` Hier ein Beispiel:

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

Beim Aufrufen der `trafficLights` Enumeration können die Argumente nur`solidRed`, `solidYellow``solidGreen`, usw. sein. Es ist üblich, Aufzählungen zu verwenden, um Dinge darzustellen, für die es eine bestimmte, aber begrenzte Anzahl von Auswahlmöglichkeiten gibt.

## Unionen/Schnittstellen
<a name="union-interface-components"></a>

Siehe [Schnittstellen und Unions](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html) in GraphQL.

# GraphQL-Felder
<a name="graphql-fields"></a>

Felder existieren innerhalb des Gültigkeitsbereichs eines Typs und enthalten den Wert, der vom GraphQL-Dienst angefordert wird. Diese sind Variablen in anderen Programmiersprachen sehr ähnlich. Hier ist zum Beispiel ein `Person` Objekttyp:

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

Die Felder sind in diesem Fall `name` und `age` und enthalten jeweils einen `String` `Int` Und-Wert. Objektfelder wie die oben gezeigten können als Eingaben in den Feldern (Operationen) Ihrer Abfragen und Mutationen verwendet werden. Sehen Sie sich zum Beispiel Folgendes `Query` an:

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

Das `people` Feld fordert alle Instanzen von `Person` aus der Datenquelle an. Wenn Sie a `Person` in Ihrem GraphQL-Server hinzufügen oder abrufen, können Sie davon ausgehen, dass die Daten dem Format Ihrer Typen und Felder folgen, das heißt, die Struktur Ihrer Daten im Schema bestimmt, wie sie in Ihrer Antwort strukturiert werden:

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

Felder spielen eine wichtige Rolle bei der Strukturierung von Daten. Im Folgenden werden einige zusätzliche Eigenschaften erläutert, die zur weiteren Anpassung auf Felder angewendet werden können.

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

In Listen werden alle Elemente eines bestimmten Typs zurückgegeben. Mit Hilfe von Klammern kann dem Typ eines Felds eine Liste hinzugefügt werden`[]`: 

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

In `Query` `Person` geben die umgebenden Klammern an, dass Sie alle Instanzen von `Person` aus der Datenquelle als Array zurückgeben möchten. In der Antwort `Person` werden die `age` Werte `name` und jeweils als eine einzige, durch Trennzeichen getrennte Liste zurückgegeben:

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

Sie sind nicht auf spezielle Objekttypen beschränkt. Sie können Listen auch in den Feldern regulärer Objekttypen verwenden.

## Werte, die nicht NULL sind
<a name="non-null-components"></a>

Werte, die nicht NULL sind, geben ein Feld an, das in der Antwort nicht Null sein darf. Sie können ein Feld mit dem folgenden Symbol auf einen Wert ungleich Null setzen: `!`

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

Das `name` Feld kann nicht explizit Null sein. Wenn Sie die Datenquelle abfragen und eine Nulleingabe für dieses Feld angeben würden, würde ein Fehler ausgegeben.

Sie können Listen und Nicht-Null-Werte kombinieren. Vergleichen Sie diese Abfragen:

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

.
.
.

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

.
.
.

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

In Anwendungsfall 1 darf die Liste keine Nullelemente enthalten. Im Anwendungsfall 2 kann die Liste selbst nicht auf Null gesetzt werden. Im Anwendungsfall 3 dürfen die Liste und ihre Elemente nicht Null sein. In jedem Fall können Sie jedoch immer noch leere Listen zurückgeben.

Wie Sie sehen können, gibt es in GraphQL viele bewegliche Komponenten. In diesem Abschnitt haben wir die Struktur eines einfachen Schemas und die verschiedenen Typen und Felder gezeigt, die ein Schema unterstützt. Im folgenden Abschnitt erfahren Sie mehr über die anderen Komponenten einer GraphQL-API und wie sie mit dem Schema funktionieren.