

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 und Architektur AWS AppSync
<a name="graphql-overview"></a>

**Anmerkung**  
In diesem Handbuch wird davon ausgegangen, dass der Benutzer über fundierte Kenntnisse des REST-Architekturstils verfügt. Wir empfehlen, dieses und andere Frontend-Themen zu lesen, bevor Sie mit GraphQL arbeiten und. AWS AppSync

GraphQL ist eine Abfrage- und Manipulationssprache für APIs. GraphQL bietet eine flexible und intuitive Syntax zur Beschreibung von Datenanforderungen und Interaktionen. Es ermöglicht Entwicklern, genau nach dem zu fragen, was benötigt wird, und vorhersehbare Ergebnisse zu erhalten. Es ermöglicht auch den Zugriff auf viele Quellen in einer einzigen Anfrage, wodurch die Anzahl der Netzwerkaufrufe und die Bandbreitenanforderungen reduziert werden, wodurch die Akkulaufzeit und die CPU-Zyklen, die von Anwendungen verbraucht werden, reduziert werden. 

Das Aktualisieren von Daten wird durch Mutationen vereinfacht, sodass Entwickler beschreiben können, wie sich die Daten ändern sollten. GraphQL ermöglicht auch die schnelle Einrichtung von Echtzeitlösungen über Abonnements. All diese Funktionen in Kombination mit leistungsstarken Entwicklertools machen GraphQL für die Verwaltung von Anwendungsdaten unverzichtbar.

GraphQL ist eine Alternative zu REST. RESTful Architektur ist derzeit eine der beliebtesten Lösungen für die Client-Server-Kommunikation. Im Mittelpunkt steht das Konzept, dass Ihre Ressourcen (Daten) über eine URL verfügbar gemacht werden. Diese URLs können verwendet werden, um über CRUD-Operationen (Create, Read, Update, Delete) in Form von HTTP-Methoden wie `GET``POST`, und auf die Daten zuzugreifen und `DELETE` sie zu bearbeiten. Der Vorteil von REST besteht darin, dass es relativ einfach zu erlernen und zu implementieren ist. Sie können schnell einrichten RESTful APIs , um eine Vielzahl von Diensten anzurufen. 

Die Technologie wird jedoch immer komplizierter. Da Anwendungen, Tools und Dienste zunehmend für ein weltweites Publikum skaliert werden, ist der Bedarf an schnellen, skalierbaren Architekturen von größter Bedeutung. REST weist viele Mängel auf, wenn es um skalierbare Abläufe geht. In diesem [Anwendungsfall](https://aws.amazon.com/blogs/architecture/what-to-consider-when-modernizing-apis-with-graphql-on-aws/) finden Sie ein Beispiel.

In den folgenden Abschnitten werden wir uns mit einigen der damit verbundenen Konzepte befassen RESTful APIs. Anschließend stellen wir GraphQL vor und wie es funktioniert.

Weitere Informationen zu GraphQL und den Vorteilen der Migration zu AWS finden Sie im [Entscheidungsleitfaden für GraphQL-Implementierungen](https://aws.amazon.com/graphql/guide/).

**Topics**
+ [Was ist eine API](what-is-an-api.md)
+ [Was ist REST](what-is-rest.md)
+ [Was ist GraphQL](what-is-graphql.md)
+ [Vergleich von REST und GraphQL](comparing-rest-graphql.md)
+ [Warum GraphQL gegenüber REST verwenden](why-use-graphql.md)
+ [Komponenten einer GraphQL-API](api-components.md)
+ [Zusätzliche Eigenschaften von GraphQL](graphql-properties.md)

# Was ist eine API?
<a name="what-is-an-api"></a>

Eine Anwendungsprogrammierschnittstelle (API) definiert die Regeln, die Sie befolgen müssen, um mit anderen Softwaresystemen zu kommunizieren. Entwickler veröffentlichen oder erstellen Inhalte, APIs sodass andere Anwendungen programmgesteuert mit ihren Anwendungen kommunizieren können. Die Timesheet-Anwendung stellt beispielsweise eine API zur Verfügung, die nach dem vollständigen Namen eines Mitarbeiters und einem Datumsbereich fragt. Wenn sie diese Informationen erhält, verarbeitet sie intern die Arbeitszeittabelle des Mitarbeiters und gibt die Anzahl der Arbeitsstunden in diesem Zeitraum zurück.

Sie können sich eine Web-API als ein Gateway zwischen Clients und Ressourcen im Internet vorstellen.

## Clients
<a name="what-is-a-client"></a>

Kunden sind Benutzer, die auf Informationen aus dem Internet zugreifen möchten. Der Client kann eine Person oder ein Softwaresystem sein, das die API verwendet. Entwickler können beispielsweise Programme schreiben, die auf Wetterdaten von einem Wettersystem zugreifen. Oder Sie können über Ihren Browser auf dieselben Daten zugreifen, wenn Sie die Wetter-Website direkt besuchen.

## Ressourcen
<a name="what-is-a-resource"></a>

Ressourcen sind die Informationen, die verschiedene Anwendungen ihren Kunden zur Verfügung stellen. Ressourcen können Bilder, Videos, Text, Zahlen oder jede Art von Daten sein. Der Computer, der die Ressource an den Client weitergibt, wird auch als Server bezeichnet. Organizations nutzen APIs Ressourcen gemeinsam und stellen Webdienste bereit, ohne dabei Sicherheit, Kontrolle und Authentifizierung zu vernachlässigen. APIs Helfen Sie ihnen außerdem dabei, festzustellen, welche Kunden Zugriff auf bestimmte interne Ressourcen erhalten.

# Was ist REST?
<a name="what-is-rest"></a>

Auf einer höheren Ebene ist Representational State Transfer (REST) eine Softwarearchitektur, die Bedingungen dafür festlegt, wie eine API funktionieren sollte. REST wurde ursprünglich als Richtlinie für die Verwaltung der Kommunikation in einem komplexen Netzwerk wie dem Internet entwickelt. Sie können eine REST-basierte Architektur verwenden, um leistungsstarke und zuverlässige Kommunikation in großem Maßstab zu unterstützen. Sie können sie einfach implementieren und modifizieren und so Transparenz und plattformübergreifende Portabilität für jedes API-System schaffen.

API-Entwickler können APIs mit verschiedenen Architekturen entwerfen. APIs die dem REST-Architekturstil folgen, werden REST APIs genannt. Webdienste, die die REST-Architektur implementieren, werden als RESTful Webdienste bezeichnet. Der Begriff RESTful API bezieht sich im Allgemeinen auf RESTful Web APIs. Sie können die Begriffe REST-API und RESTful API jedoch synonym verwenden.

Im Folgenden sind einige der Prinzipien des REST-Architekturstils aufgeführt:

## Einheitliche Oberfläche
<a name="uniform-interface"></a>

Die einheitliche Oberfläche ist grundlegend für das Design eines jeden RESTful Webservices. Es zeigt an, dass der Server Informationen in einem Standardformat überträgt. Die formatierte Ressource wird in REST als Repräsentation bezeichnet. Dieses Format kann sich von der internen Darstellung der Ressource in der Serveranwendung unterscheiden. Beispielsweise kann der Server Daten als Text speichern, sie aber in einem HTML-Darstellungsformat senden.

Eine einheitliche Benutzeroberfläche unterliegt vier architektonischen Einschränkungen:

1.  Anfragen sollten Ressourcen identifizieren. Sie tun dies, indem sie eine einheitliche Ressourcenkennung verwenden. 

1.  Die Ressourcendarstellung der Clients enthält genügend Informationen, um die Ressource bei Bedarf zu ändern oder zu löschen. Der Server erfüllt diese Bedingung, indem er Metadaten sendet, die die Ressource näher beschreiben. 

1.  Kunden erhalten Informationen darüber, wie die Darstellung weiter verarbeitet werden kann. Der Server erreicht dies, indem er selbstbeschreibende Nachrichten sendet, die Metadaten darüber enthalten, wie der Client sie am besten verwenden kann. 

1.  Die Clients erhalten Informationen über alle anderen zugehörigen Ressourcen, die sie zum Erledigen einer Aufgabe benötigen. Der Server erreicht dies, indem er Hyperlinks in der Darstellung sendet, sodass Clients dynamisch mehr Ressourcen ermitteln können. 

## Staatenlosigkeit
<a name="statelessness"></a>

In der REST-Architektur bezieht sich Zustandslosigkeit auf eine Kommunikationsmethode, bei der der Server jede Client-Anfrage unabhängig von allen vorherigen Anfragen abschließt. Clients können Ressourcen in beliebiger Reihenfolge anfordern, und jede Anfrage ist zustandslos oder isoliert von anderen Anfragen. Diese Rest-API-Designeinschränkung impliziert, dass der Server die Anfrage jedes Mal vollständig verstehen und erfüllen kann. 

## Mehrschichtiges System
<a name="layered-system"></a>

In einer mehrschichtigen Systemarchitektur kann der Client eine Verbindung zu anderen autorisierten Vermittlern zwischen dem Client und dem Server herstellen und erhält weiterhin Antworten vom Server. Server können Anfragen auch an andere Server weiterleiten. Sie können Ihren RESTful Webservice so gestalten, dass er auf mehreren Servern mit mehreren Ebenen wie Sicherheits-, Anwendungs- und Geschäftslogik ausgeführt wird, die zusammenarbeiten, um Kundenanfragen zu erfüllen. Diese Ebenen bleiben für den Client unsichtbar.

## Cachefähigkeit
<a name="cacheability"></a>

RESTful Webdienste unterstützen das Zwischenspeichern, bei dem einige Antworten auf dem Client oder auf einem Zwischenspeicher gespeichert werden, um die Antwortzeit des Servers zu verbessern. Nehmen wir zum Beispiel an, Sie besuchen eine Website, die auf jeder Seite gemeinsame Kopf- und Fußzeilenbilder enthält. Jedes Mal, wenn Sie eine neue Website besuchen, muss der Server dieselben Bilder erneut senden. Um dies zu vermeiden, speichert der Client diese Bilder nach der ersten Antwort im Cache oder speichert sie und verwendet die Bilder dann direkt aus dem Cache. RESTful Webdienste steuern das Caching mithilfe von API-Antworten, die sich selbst als zwischenspeicherbar oder nicht zwischenspeicherbar definieren.

## Was ist eine API? RESTful
<a name="what-is-a-restful-api"></a>

RESTful API ist eine Schnittstelle, über die zwei Computersysteme Informationen sicher über das Internet austauschen. Die meisten Geschäftsanwendungen müssen mit anderen internen Anwendungen und Anwendungen von Drittanbietern kommunizieren, um verschiedene Aufgaben ausführen zu können. Um beispielsweise monatliche Gehaltsabrechnungen zu erstellen, muss Ihr internes Buchhaltungssystem Daten mit dem Banksystem Ihres Kunden teilen, um die Rechnungsstellung zu automatisieren und mit einer internen Arbeitszeiterfassungsanwendung zu kommunizieren. RESTful APIs unterstützen diesen Informationsaustausch, weil sie sicheren, zuverlässigen und effizienten Software-Kommunikationsstandards folgen.

## Wie RESTful APIs arbeiten sie?
<a name="how-do-restful-apis-work"></a>

Die grundlegende Funktion einer RESTful API entspricht dem Surfen im Internet. Der Client kontaktiert den Server über die API, wenn er eine Ressource benötigt. API-Entwickler erklären in der API-Dokumentation der Serveranwendung, wie der Client die REST-API verwenden sollte. Dies sind die allgemeinen Schritte für jeden REST-API-Aufruf:

1.  Der Client sendet eine Anfrage an den Server. Der Client folgt der API-Dokumentation, um die Anfrage so zu formatieren, dass der Server sie versteht. 

1.  Der Server authentifiziert den Client und bestätigt, dass der Client berechtigt ist, diese Anfrage zu stellen. 

1.  Der Server empfängt die Anfrage und verarbeitet sie intern. 

1.  Der Server gibt eine Antwort an den Client zurück. Die Antwort enthält Informationen, die dem Client mitteilen, ob die Anfrage erfolgreich war. Die Antwort enthält auch alle Informationen, die der Client angefordert hat. 

Die Details der REST-API-Anfrage und der Antwort variieren geringfügig, je nachdem, wie die API-Entwickler die API entwerfen.

# Was ist GraphQL?
<a name="what-is-graphql"></a>

GraphQL ist sowohl eine Abfragesprache für APIs als auch eine Laufzeit für die Ausführung dieser Abfragen. GraphQL ermöglicht es Kunden, genau die Daten anzufordern, die sie benötigen, was in vielen Szenarien eine flexiblere und effizientere Alternative zu REST darstellt. Im Gegensatz zu REST, das auf vordefinierten Endpunkten basiert, verwendet GraphQL einen einzigen Endpunkt, an dem Clients ihre Datenanforderungen in Form von Abfragen und Mutationen spezifizieren können. 

Weitere Informationen [zur Struktur von GraphQL finden Sie unter Komponenten einer APIs GraphQL-API](https://docs.aws.amazon.com/appsync/latest/devguide/api-components.html).

# Vergleich von REST und GraphQL
<a name="comparing-rest-graphql"></a>

APIs (Anwendungsprogrammierschnittstellen) spielen eine entscheidende Rolle bei der Erleichterung des Datenaustauschs zwischen Anwendungen. Wie bereits erwähnt, APIs haben sich zwei herausragende Designansätze herauskristallisiert: GraphQL und REST. Beide dienen zwar dem grundlegenden Zweck, die Client-Server-Kommunikation zu ermöglichen, unterscheiden sich jedoch erheblich in ihrer Implementierung und ihren Anwendungsfällen.

GraphQL und REST haben mehrere Hauptmerkmale gemeinsam: 

1. **Client-Server-Modell**: Beide verwenden eine Client-Server-Architektur für den Datenaustausch. 

1. **Staatenlosigkeit**: Keiner von beiden verwaltet Informationen zur Clientsitzung zwischen Anfragen. 

1. **HTTP-basiert**: Beide verwenden in der Regel HTTP als zugrundeliegendes Kommunikationsprotokoll. 

1. **Ressourcenorientiertes Design**: Beide gestalten ihren Datenaustausch auf der Grundlage von Ressourcen, die sich auf alle Daten oder Objekte beziehen, auf die der Client über die API zugreifen und sie bearbeiten kann. 

1. **Flexibilität des Datenformats**: JSON ist in beiden Fällen das am häufigsten verwendete Datenaustauschformat, obwohl auch andere Formate wie XML und HTML unterstützt werden. 

1. **Sprach- und datenbankunabhängig**: Beide können mit jeder Programmiersprache oder Datenbankstruktur arbeiten, wodurch sie in hohem Maße interoperabel sind. 

1. **Caching-Unterstützung**: Beide unterstützen Caching, sodass Clients und Server häufig aufgerufene Daten speichern können, um die Leistung zu verbessern. 

GraphQL und REST teilen zwar einige grundlegende Prinzipien, unterscheiden sich jedoch erheblich in ihrem Ansatz für API-Design und Datenabruf:

1. **Anforderungsstruktur und Datenabruf**

   REST verwendet verschiedene HTTP-Methoden (GET, POST, PUT, DELETE), um Operationen mit Ressourcen durchzuführen. Dies erfordert häufig mehrere Endpunkte für unterschiedliche Ressourcen, was zu Ineffizienzen beim Datenabruf führen kann. Beispielsweise kann das Ausführen eines GET-Vorgangs zum Abrufen der Daten eines Benutzers dazu führen, dass Daten zu viel oder zu wenig abgerufen werden. Um die richtigen Daten zu erhalten, können Kürzung oder mehrere Operationen aufgerufen werden. 

   GraphQL verwendet einen einzigen Endpunkt für alle Operationen. Es stützt sich auf Abfragen zum Abrufen von Daten und Mutationen zum Ändern von Daten. Clients können Abfragen verwenden, um mit einer einzigen Anfrage genau die Daten abzurufen, die sie benötigen, wodurch der Netzwerkaufwand durch Minimierung der Datenübertragung reduziert wird. 

1. **Serverseitiges Schema**

   REST benötigt kein serverseitiges Schema, obwohl eines optional definiert werden kann, um ein effizientes API-Design und eine effiziente API-Dokumentation zu gewährleisten.

   GraphQL verwendet ein stark typisiertes serverseitiges Schema, um Daten und Datendienste zu definieren. Das in GraphQL Schema Definition Language (SDL) geschriebene Schema umfasst Objekttypen und Felder für jedes Objekt sowie serverseitige Resolverfunktionen, die Operationen für jedes Feld definieren.

1. **Versioning**

   REST beinhaltet häufig die Versionierung in der URL, was dazu führen kann, dass mehrere API-Versionen gleichzeitig verwaltet werden. Die Versionierung ist nicht verpflichtend, kann aber dazu beitragen, grundlegende Änderungen zu verhindern. 

   GraphQL fördert eine kontinuierliche Weiterentwicklung der API ohne explizite Versionierung, indem es Abwärtskompatibilität erfordert. Gelöschte Felder geben Fehlermeldungen zurück, während veraltete Tags alte Felder auslaufen lassen und Warnmeldungen zurückgeben. 

1. **Behandlung von Fehlern** 

   REST ist schwach typisiert, sodass die Fehlerbehandlung in den umgebenden Code integriert werden muss. Dadurch werden typbezogene Fehler (z. B. das Parsen einer Zahl als Text) möglicherweise nicht automatisch erkannt. 

   Im Gegensatz dazu ist GraphQL stark typisiert und erfordert eine umfassende Schemadefinition. Auf diese Weise kann Ihr Service viele Anforderungsfehler automatisch und mit einem hohen Detaillierungsgrad identifizieren.

1. **Anwendungsfälle**

   REST ist besser geeignet für: 
   + Kleinere Anwendungen mit weniger komplexen Datenanforderungen. 
   + Szenarien, in denen Daten und Operationen von allen Clients auf ähnliche Weise verwendet werden. 
   + Anwendungen ohne komplexe Datenabfrageanforderungen. 

   GraphQL ist besser geeignet für: 
   + Szenarien mit begrenzter Bandbreite, in denen die Minimierung von Anfragen und Antworten entscheidend ist. 
   + Anwendungen mit mehreren Datenquellen, die an einem einzigen Endpunkt kombiniert werden müssen. 
   + Fälle, in denen Kundenanfragen stark variieren und unterschiedliche Antwortstrukturen erwartet werden.

   Beachten Sie, dass es möglich ist, sowohl GraphQL als auch REST APIs in einer einzigen Anwendung für verschiedene Funktionsbereiche zu verwenden. Darüber hinaus können Sie eine RESTful API so aktualisieren, dass sie GraphQL-Funktionen enthält, ohne sie komplett neu schreiben zu müssen. Ein [Beispiel finden Sie unter So erstellen Sie GraphQL-Resolver für AWS Datenquellen](https://aws.amazon.com/graphql/resolvers/).

# Warum GraphQL über REST verwenden?
<a name="why-use-graphql"></a>

REST ist einer der Eckpfeiler der Architektur des Webs. APIs Da die Welt jedoch immer stärker vernetzt wird, wird die Notwendigkeit, robuste und skalierbare Anwendungen zu entwickeln, zu einem immer dringlicheren Problem werden. REST wird zwar häufig zur Erstellung von Websites verwendet APIs, es wurden jedoch mehrere wiederkehrende Nachteile bei RESTful Implementierungen festgestellt:

1. **Datenanfragen**: Mit dieser Methode RESTful APIs würden Sie die benötigten Daten in der Regel über Endgeräte anfordern. Das Problem tritt auf, wenn Sie Daten haben, die möglicherweise nicht so übersichtlich verpackt sind. Die Daten, die Sie benötigen, befinden sich möglicherweise hinter mehreren Abstraktionsebenen, und die einzige Möglichkeit, die Daten abzurufen, besteht darin, mehrere Endpunkte zu verwenden, was bedeutet, dass mehrere Anfragen zum Extrahieren aller Daten gestellt werden müssen.

1. Zu **viel und zu wenig abrufen**: Um die Probleme mehrerer Anfragen noch zu verschärfen, sind die Daten von jedem Endpunkt genau definiert, was bedeutet, dass Sie alle Daten zurückgeben, die für diese API definiert wurden, auch wenn Sie sie technisch nicht wollten.

   Dies kann zu *übermäßigem Abrufen* führen, was bedeutet, dass unsere Anfragen überflüssige Daten zurückgeben. Nehmen wir zum Beispiel an, Sie fordern Personaldaten des Unternehmens an und möchten die Namen der Mitarbeiter in einer bestimmten Abteilung wissen. Der Endpunkt, der die Daten zurückgibt, enthält die Namen, kann aber auch andere Daten wie Berufsbezeichnung oder Geburtsdatum enthalten. Da die API fest ist, können Sie nicht einfach nur die Namen anfordern. Der Rest der Daten wird mitgeliefert.

   Die gegenteilige Situation, in der wir nicht genügend Daten zurückgeben, wird als *Unterabruf* bezeichnet. Um alle angeforderten Daten zu erhalten, müssen Sie möglicherweise mehrere Anfragen an den Dienst stellen. Je nachdem, wie die Daten strukturiert waren, könnten Sie auf ineffiziente Abfragen stoßen, die zu Problemen wie dem gefürchteten n\$11-Problem führten.

1. **Langsame Entwicklungsiterationen**: Viele Entwickler passen sie RESTful APIs an den Ablauf ihrer Anwendungen an. Wenn ihre Anwendungen jedoch wachsen, können sowohl die Front- als auch die Backends umfangreiche Änderungen erfordern. Infolgedessen passen sie sich APIs möglicherweise nicht mehr effizient oder wirkungsvoll der Form der Daten an. Dies führt aufgrund der Notwendigkeit von API-Änderungen zu langsameren Produktiterationen.

1. **Skalierbare Leistung**: Aufgrund dieser sich verschärfenden Probleme gibt es viele Bereiche, in denen die Skalierbarkeit beeinträchtigt wird. Die Leistung auf der Anwendungsseite kann beeinträchtigt werden, weil Ihre Anfragen zu viele oder zu wenig Daten zurückgeben (was zu mehr Anfragen führt). In beiden Situationen wird das Netzwerk unnötig belastet, was zu einer schlechten Leistung führt. Auf Seiten der Entwickler kann die Geschwindigkeit der Entwicklung reduziert werden, weil Sie nicht mehr richtig APIs sind und nicht mehr zu den Daten passen, die sie anfordern.

Das Verkaufsargument von GraphQL besteht darin, die Nachteile von REST zu überwinden. Hier sind einige der wichtigsten Lösungen, die GraphQL Entwicklern bietet:

1. **Einzelne Endpunkte**: GraphQL verwendet einen einzigen Endpunkt, um Daten abzufragen. Es ist nicht erforderlich, mehrere zu erstellen, APIs um sie an die Form der Daten anzupassen. Dies führt dazu, dass weniger Anfragen über das Netzwerk gesendet werden.

1. **Abrufen**: GraphQL löst die ständigen Probleme des Über- und Unterabrufs, indem es einfach die Daten definiert, die Sie benötigen. Mit GraphQL können Sie die Daten an Ihre Bedürfnisse anpassen, sodass Sie nur das erhalten, wonach Sie gefragt haben.

1. **Abstraktion**: GraphQL APIs enthält einige Komponenten und Systeme, die die Daten mithilfe eines sprachunabhängigen Standards beschreiben. Mit anderen Worten, Form und Struktur der Daten sind standardisiert, sodass sowohl das Front- als auch das Backend wissen, wie sie über das Netzwerk gesendet werden. Dies ermöglicht es Entwicklern an beiden Enden, mit den Systemen von GraphQL zu arbeiten und nicht um sie herum.

1. **Schnelle Iterationen**: Aufgrund der Standardisierung der Daten sind Änderungen an einem Ende der Entwicklung am anderen Ende möglicherweise nicht erforderlich. Beispielsweise führen Änderungen an der Frontend-Präsentation möglicherweise nicht zu umfangreichen Änderungen am Backend, da GraphQL die einfache Änderung der Datenspezifikation ermöglicht. Sie können einfach die Form der Daten definieren oder ändern, um sie an die Anforderungen der Anwendung anzupassen, wenn sie wächst. Dies führt zu weniger potenziellem Entwicklungsaufwand.

Dies sind nur einige der Vorteile von GraphQL. In den nächsten Abschnitten erfahren Sie, wie GraphQL strukturiert ist und welche Eigenschaften es zu einer einzigartigen Alternative zu REST machen.

# Komponenten einer GraphQL-API
<a name="api-components"></a>

Eine Standard-GraphQL-API besteht aus einem einzigen Schema, das die Form der abgefragten Daten behandelt. Ihr Schema ist mit einer oder mehreren Ihrer Datenquellen wie einer Datenbank oder einer Lambda-Funktion verknüpft. Dazwischen befinden sich ein oder mehrere Resolver, die die Geschäftslogik für Ihre Anfragen verwalten. Jede Komponente spielt eine wichtige Rolle in Ihrer GraphQL-Implementierung. In den folgenden Abschnitten werden diese drei Komponenten und ihre Rolle im GraphQL-Dienst vorgestellt.

![\[GraphQL API components: schema, resolvers, and data sources interconnected with AppSync.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/appsync-architecture-graphql-api.png)


**Topics**
+ [GraphQL-Schemas](schema-components.md)
+ [Datenquellen](data-source-components.md)
+ [Resolver](resolver-components.md)

# 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.

# Datenquellen
<a name="data-source-components"></a>

Im vorherigen Abschnitt haben wir gelernt, dass ein Schema die Form Ihrer Daten definiert. Wir haben jedoch nie erklärt, woher diese Daten stammen. In echten Projekten ist Ihr Schema wie ein Gateway, das alle Anfragen an den Server verarbeitet. Wenn eine Anfrage gestellt wird, fungiert das Schema als einziger Endpunkt, der mit dem Client verbunden ist. Das Schema greift auf Daten aus der Datenquelle zu, verarbeitet sie und leitet sie zurück an den Client weiter. Sehen Sie sich die folgende Infografik an:

![\[GraphQL schema integrating multiple AWS-Services for a single endpoint API architecture.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/aws-flow-infographic.png)


AWS AppSync und GraphQL implementieren hervorragend Backend For Frontend (BFF) -Lösungen. Sie arbeiten zusammen, um die Komplexität skalierbar zu reduzieren, indem sie das Backend abstrahieren. Wenn Ihr Service unterschiedliche Datenquellen und/oder Microservices verwendet, können Sie im Wesentlichen einen Teil der Komplexität abstrahieren, indem Sie die Form der Daten jeder Quelle (Untergraph) in einem einzigen Schema (Supergraph) definieren. Das bedeutet, dass Ihre GraphQL-API nicht auf die Verwendung einer Datenquelle beschränkt ist. Sie können Ihrer GraphQL-API eine beliebige Anzahl von Datenquellen zuordnen und in Ihrem Code angeben, wie sie mit dem Dienst interagieren sollen.

Wie Sie in der Infografik sehen können, enthält das GraphQL-Schema alle Informationen, die Clients benötigen, um Daten anzufordern. Das bedeutet, dass alles in einer einzigen Anfrage verarbeitet werden kann und nicht in mehreren Anfragen, wie es bei REST der Fall ist. Diese Anfragen durchlaufen das Schema, das der einzige Endpunkt des Dienstes ist. Wenn Anfragen verarbeitet werden, führt ein Resolver (im nächsten Abschnitt erklärt) seinen Code aus, um die Daten aus der entsprechenden Datenquelle zu verarbeiten. Wenn die Antwort zurückgegeben wird, wird der mit der Datenquelle verknüpfte Untergraph mit den Daten im Schema gefüllt. 

AWS AppSync unterstützt viele verschiedene Datenquellentypen. In der folgenden Tabelle werden wir jeden Typ beschreiben, einige der Vorteile der einzelnen Typen auflisten und nützliche Links für zusätzlichen Kontext bereitstellen.


| Datenquelle | Description | Vorteile | Zusätzliche Informationen | 
| --- | --- | --- | --- | 
| Amazon DynamoDB | „Amazon DynamoDB ist ein vollständig verwalteter NoSQL-Datenbankservice, der schnelle und vorhersehbare Leistung mit nahtloser Skalierbarkeit bietet. Mit DynamoDB können Sie den Verwaltungsaufwand für den Betrieb und die Skalierung verteilter Datenbanken verringern, sodass Sie sich nicht um Hardwarebereitstellung, Einrichtung und Konfiguration, Replikation, Software-Patching oder Cluster-Skalierung kümmern müssen. DynamoDB bietet auch Verschlüsselung im Ruhezustand, wodurch der betriebliche Aufwand und die Komplexität, die mit dem Schutz sensibler Daten verbunden sind, entfallen.“ |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| AWS Lambda | "AWS Lambda ist ein Rechendienst, mit dem Sie Code ausführen können, ohne Server bereitstellen oder verwalten zu müssen.Lambda führt Ihren Code auf einer hochverfügbaren Recheninfrastruktur aus und führt die gesamte Verwaltung der Rechenressourcen durch, einschließlich Server- und Betriebssystemwartung, Kapazitätsbereitstellung und automatischer Skalierung sowie Protokollierung. Mit Lambda müssen Sie lediglich Ihren Code in einer der von Lambda unterstützten Sprachlaufzeiten bereitstellen.“ |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| OpenSearch | „Amazon OpenSearch Service ist ein verwalteter Service, der es einfach macht, OpenSearch Cluster in der AWS Cloud bereitzustellen, zu betreiben und zu skalieren. Amazon OpenSearch Service unterstützt OpenSearch ältere Elasticsearch-Betriebssysteme (bis zu 7.10, die endgültige Open-Source-Version der Software). Wenn Sie einen Cluster erstellen, haben Sie die Option, die Suchmaschine zu verwenden.**OpenSearch**ist eine vollständig quelloffene Such- und Analyse-Engine für Anwendungsfälle wie Protokollanalysen, Anwendungsüberwachung in Echtzeit und Clickstream-Analyse. Weitere Informationen finden Sie in der [OpenSearch-Dokumentation](https://opensearch.org/docs/).**Amazon OpenSearch Service** stellt alle Ressourcen für Ihren OpenSearch Cluster bereit und startet ihn. Außerdem werden ausgefallene OpenSearch Serviceknoten automatisch erkannt und ersetzt, wodurch der mit selbstverwalteten Infrastrukturen verbundene Aufwand reduziert wird. Sie können Ihren Cluster mit einem einzigen API-Aufruf oder mit ein paar Klicks in der Konsole skalieren.“ |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| HTTP-Endpunkte | Sie können HTTP-Endpunkte als Datenquellen verwenden. AWS AppSync kann Anfragen mit den relevanten Informationen wie Parametern und Nutzdaten an die Endpunkte senden. Die HTTP-Antwort wird dem Resolver zugänglich gemacht, der die endgültige Antwort zurückgibt, nachdem er seine Operation (en) abgeschlossen hat. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| Amazon EventBridge | "EventBridge ist ein serverloser Service, der Ereignisse verwendet, um Anwendungskomponenten miteinander zu verbinden, sodass Sie leichter skalierbare, ereignisgesteuerte Anwendungen erstellen können. Verwenden Sie ihn, um Ereignisse aus Quellen wie selbst entwickelten Anwendungen, AWS Diensten und Software von Drittanbietern an Verbraucheranwendungen in Ihrem Unternehmen weiterzuleiten. EventBridge bietet eine einfache und konsistente Methode zum Erfassen, Filtern, Transformieren und Bereitstellen von Ereignissen, sodass Sie schnell neue Anwendungen erstellen können.“ |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| Relationale Datenbanken | „Amazon Relational Database Service (Amazon RDS) ist ein Webservice, der die Einrichtung, den Betrieb und die Skalierung einer relationalen Datenbank in der AWS Cloud erleichtert. Er bietet kosteneffiziente, anpassbare Kapazität für eine relationale Datenbank nach Industriestandard und verwaltet allgemeine Datenbankverwaltungsaufgaben.“ |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 
| Keine Datenquelle | Wenn Sie nicht vorhaben, einen Datenquellendienst zu verwenden, können Sie ihn auf einstellennone. Eine none Datenquelle ist zwar immer noch explizit als Datenquelle kategorisiert, aber kein Speichermedium. Trotzdem ist es in bestimmten Fällen immer noch nützlich, um Daten zu manipulieren und weiterzuleiten. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/data-source-components.html)  | 

**Tipp**  
Weitere Informationen zur Interaktion zwischen Datenquellen finden Sie AWS AppSync unter [Anhängen einer Datenquelle](https://docs.aws.amazon.com//appsync/latest/devguide/attaching-a-data-source.html).

# Resolver
<a name="resolver-components"></a>

In den vorherigen Abschnitten haben Sie sich mit den Komponenten des Schemas und der Datenquelle vertraut gemacht. Jetzt müssen wir uns damit befassen, wie das Schema und die Datenquellen interagieren. Alles beginnt mit dem Resolver.

Ein Resolver ist eine Codeeinheit, die regelt, wie die Daten dieses Felds aufgelöst werden, wenn eine Anfrage an den Dienst gestellt wird. Resolver sind an bestimmte Felder innerhalb Ihrer Typen in Ihrem Schema angehängt. Sie werden am häufigsten verwendet, um die Zustandsänderungsoperationen für Ihre Abfrage-, Mutations- und Abonnement-Feldoperationen zu implementieren. Der Resolver verarbeitet die Anfrage eines Clients und gibt dann das Ergebnis zurück. Dabei kann es sich um eine Gruppe von Ausgabetypen wie Objekten oder Skalaren handeln:

![\[GraphQL schema with resolvers connecting to various AWS data sources for a single endpoint.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/aws-flow-infographic.png)


## Laufzeit des Resolvers
<a name="resolver-components-runtime"></a>

 AWS AppSync In müssen Sie zunächst eine Laufzeit für Ihren Resolver angeben. Eine Resolver-Runtime gibt die Umgebung an, in der ein Resolver ausgeführt wird. Sie bestimmt auch die Sprache, in der Ihre Resolver geschrieben werden. AWS AppSync unterstützt derzeit APPSYNC\$1JS für JavaScript und Velocity Template Language (VTL). Weitere Informationen finden Sie unter [JavaScript Laufzeitfunktionen für Resolver und Funktionen](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) für JavaScript oder Referenz zum [Resolver Mapping](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html) Template Utility für VTL.

## Resolver-Struktur
<a name="resolver-components-structure"></a>

Was den Code angeht, können Resolver auf verschiedene Arten strukturiert werden. **Es gibt **Unit** - und Pipeline-Resolver.**

### Resolver für Einheiten
<a name="resolver-components-unit"></a>

Ein Unit-Resolver besteht aus Code, der einen einzelnen Anforderungs- und Antworthandler definiert, die für eine Datenquelle ausgeführt werden. Der Anforderungshandler verwendet ein Kontextobjekt als Argument und gibt die Anforderungsnutzdaten zurück, die zum Aufrufen Ihrer Datenquelle verwendet wurden. Der Antworthandler erhält von der Datenquelle eine Nutzlast mit dem Ergebnis der ausgeführten Anfrage zurück. Der Response-Handler wandelt die Nutzlast in eine GraphQL-Antwort um, um das GraphQL-Feld aufzulösen.

![\[GraphQL request flow showing request and response handlers interacting with a data source.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/unit-resolver-js.png)


### Pipeline-Resolver
<a name="resolver-components-pipeline"></a>

Bei der Implementierung von Pipeline-Resolvern gibt es eine allgemeine Struktur, der sie folgen:
+ **Schritt vor dem**: Wenn eine Anfrage vom Client gestellt wird, werden den Resolvern für die verwendeten Schemafelder (normalerweise Ihre Abfragen, Mutationen, Abonnements) die Anforderungsdaten übergeben. Der Resolver beginnt mit der Verarbeitung der Anforderungsdaten mit einem Before-Step-Handler, der es ermöglicht, einige Vorverarbeitungsvorgänge durchzuführen, bevor die Daten den Resolver passieren.
+ **Funktion (en)**: Nachdem der vorherige Schritt ausgeführt wurde, wird die Anforderung an die Funktionsliste übergeben. Die erste Funktion in der Liste wird für die Datenquelle ausgeführt. Eine Funktion ist eine Teilmenge des Codes Ihres Resolvers, die einen eigenen Anfrage- und Antworthandler enthält. Ein Request-Handler nimmt die Anforderungsdaten und führt Operationen an der Datenquelle durch. Der Antworthandler verarbeitet die Antwort der Datenquelle, bevor er sie an die Liste zurückgibt. Wenn es mehr als eine Funktion gibt, werden die Anforderungsdaten zur Ausführung an die nächste Funktion in der Liste gesendet. Die Funktionen in der Liste werden seriell in der vom Entwickler festgelegten Reihenfolge ausgeführt. Sobald alle Funktionen ausgeführt wurden, wird das Endergebnis an den nächsten Schritt übergeben.
+ **Nach dem Schritt**: Der Nachschritt ist eine Handler-Funktion, mit der Sie einige letzte Operationen an der Antwort der endgültigen Funktion ausführen können, bevor Sie sie an die GraphQL-Antwort übergeben.

![\[GraphQL request flow diagram showing interactions between request, data sources, and response components.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/appsync-js-resolver-logic.png)


## Struktur des Resolver-Handlers
<a name="resolver-components-handlers"></a>

Handler sind in der Regel Funktionen, die aufgerufen `Request` werden und: `Response`

```
export function request(ctx) {
    // Code goes here
}

export function response(ctx) {
    // Code goes here
}
```

In einem Unit-Resolver wird es nur einen Satz dieser Funktionen geben. In einem Pipeline-Resolver wird es einen Satz dieser Funktionen für den Vorher-Nachher-Schritt und einen zusätzlichen Satz pro Funktion geben. Um zu veranschaulichen, wie das aussehen könnte, schauen wir uns einen einfachen `Query` Typ an:

```
type Query {
	helloWorld: String!
}
```

Dies ist eine einfache Abfrage mit einem Feld namens `helloWorld` Typ`String`. Nehmen wir an, wir möchten immer, dass dieses Feld die Zeichenfolge „Hello World“ zurückgibt. Um dieses Verhalten zu implementieren, müssen wir den Resolver zu diesem Feld hinzufügen. In einem Unit-Resolver könnten wir so etwas hinzufügen:

```
export function request(ctx) {
    return {}
}

export function response(ctx) {
    return "Hello World"
}
```

Das `request` kann einfach leer gelassen werden, weil wir keine Daten anfordern oder verarbeiten. Wir können auch davon ausgehen, dass unsere Datenquelle dies ist`None`, was bedeutet, dass dieser Code keine Aufrufe ausführen muss. Die Antwort gibt einfach „Hello World“ zurück. Um diesen Resolver zu testen, müssen wir eine Anfrage mit dem Abfragetyp stellen:

```
query helloWorldTest {
  helloWorld
}
```

Dies ist eine Abfrage namens`helloWorldTest`, die das `helloWorld` Feld zurückgibt. Wenn er ausgeführt wird, führt der `helloWorld` Field Resolver auch die folgende Antwort aus und gibt sie zurück:

```
{
  "data": {
    "helloWorld": "Hello World"
  }
}
```

Konstanten wie diese zurückzugeben, ist das Einfachste, was Sie tun können. In Wirklichkeit werden Sie Eingaben, Listen und mehr zurückgeben. Hier ist ein komplizierteres Beispiel:

```
type Book {
  id: ID!
  title: String
}

type Query {
  getBooks: [Book]
}
```

Hier geben wir eine Liste von zurück`Books`. Nehmen wir an, wir verwenden eine DynamoDB-Tabelle zum Speichern von Buchdaten. Unsere Handler könnten so aussehen:

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  return { operation: 'Scan' };
}

/**
 * return a list of scanned post items
 */
export function response(ctx) {
  return ctx.result.items;
}
```

Unsere Anfrage verwendete einen integrierten Scanvorgang, um nach allen Einträgen in der Tabelle zu suchen, speicherte die Ergebnisse im Kontext und übergab sie dann an die Antwort. In der Antwort wurden die Ergebniselemente übernommen und in der Antwort zurückgegeben:

```
{
  "data": {
    "getBooks": {
      "items": [
        {
          "id": "abcdefgh-1234-1234-1234-abcdefghijkl",
          "title": "book1"
        },
        {
          "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
          "title": "book2"
        },

        ...

      ]
    }
  }
}
```

## Resolver-Kontext
<a name="resolver-components-context"></a>

In einem Resolver muss jeder Schritt in der Kette von Handlern den Status der Daten aus den vorherigen Schritten kennen. Das Ergebnis eines Handlers kann gespeichert und als Argument an einen anderen übergeben werden. GraphQL definiert vier grundlegende Resolver-Argumente:


****  

| Resolver-Basisargumente | Description | 
| --- | --- | 
| obj, root, parent, usw. | Das Ergebnis des übergeordneten Elements. | 
| args | Die Argumente, die dem Feld in der GraphQL-Abfrage zur Verfügung gestellt werden. | 
| context | Ein Wert, der jedem Resolver zur Verfügung gestellt wird und wichtige Kontextinformationen wie den aktuell angemeldeten Benutzer oder den Zugriff auf eine Datenbank enthält. | 
| info | Ein Wert, der feldspezifische Informationen enthält, die für die aktuelle Abfrage relevant sind, sowie die Schemadetails. | 

 AWS AppSync In kann das Argument `[context](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)` (ctx) alle oben genannten Daten enthalten. Es ist ein Objekt, das pro Anfrage erstellt wird und Daten wie Autorisierungsdaten, Ergebnisdaten, Fehler, Anforderungsmetadaten usw. enthält. Der Kontext ist eine einfache Möglichkeit für Programmierer, Daten zu manipulieren, die aus anderen Teilen der Anfrage stammen. Nimm diesen Ausschnitt noch einmal:

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  return { operation: 'Scan' };
}

/**
 * return a list of scanned post items
 */
export function response(ctx) {
  return ctx.result.items;
}
```

Der Anfrage wird der Kontext (ctx) als Argument übergeben; dies ist der Status der Anfrage. Sie führt einen Scan für alle Elemente in einer Tabelle durch und speichert das Ergebnis anschließend wieder im `result` Kontext unter. Der Kontext wird dann an das Antwortargument übergeben, das auf den zugreift `result` und seinen Inhalt zurückgibt.

## Anfragen und Analyse
<a name="resolver-ast"></a>

Wenn Sie eine Abfrage an Ihren GraphQL-Dienst stellen, muss dieser vor der Ausführung einen Parsing- und Validierungsprozess durchlaufen. Ihre Anfrage wird analysiert und in einen abstrakten Syntaxbaum übersetzt. Der Inhalt des Baums wird validiert, indem mehrere Validierungsalgorithmen anhand Ihres Schemas ausgeführt werden. Nach dem Validierungsschritt werden die Knoten des Baums durchsucht und verarbeitet. Resolver werden aufgerufen, die Ergebnisse werden im Kontext gespeichert und die Antwort wird zurückgegeben. Betrachten Sie beispielsweise diese Abfrage:

```
query {
  Person {  //object type
    name  //scalar
    age   //scalar
  } 
}
```

Wir kehren `Person` mit den Feldern A `name` und `age` zurück. Wenn Sie diese Abfrage ausführen, sieht der Baum ungefähr so aus:

![\[Hierarchical diagram showing query, Person, name, and age nodes connected by arrows.\]](http://docs.aws.amazon.com/de_de/appsync/latest/devguide/images/ast-1.png)


Aus dem Baum geht hervor, dass diese Anfrage den Stamm nach dem `Query` im Schema durchsucht. Innerhalb der Abfrage wird das `Person` Feld aufgelöst. Aus früheren Beispielen wissen wir, dass dies eine Eingabe des Benutzers sein könnte, eine Werteliste usw., die höchstwahrscheinlich an einen Objekttyp gebunden `Person` ist, der die Felder enthält, die wir benötigen (`name`und`age`). Sobald diese beiden untergeordneten Felder gefunden wurden, werden sie in der angegebenen Reihenfolge (`name`gefolgt von`age`) aufgelöst. Sobald der Baum vollständig aufgelöst ist, ist die Anfrage abgeschlossen und wird an den Client zurückgesendet.

# Zusätzliche Eigenschaften von GraphQL
<a name="graphql-properties"></a>

GraphQL besteht aus mehreren Designprinzipien, um Einfachheit und Robustheit im großen Maßstab zu gewährleisten.

## Deklarativ
<a name="declarative-property"></a>

GraphQL ist deklarativ, was bedeutet, dass der Benutzer die Daten beschreibt (formt), indem er nur die Felder deklariert, die er abfragen möchte. Die Antwort gibt nur die Daten für diese Eigenschaften zurück. Hier ist zum Beispiel eine Operation, die ein `Book` Objekt in einer DynamoDB-Tabelle mit dem ISBN 13-Wert von abruft: `id` *9780199536061*

```
{
  getBook(id: "9780199536061") {
    name
    year
    author
  }
}
```

Die Antwort gibt nur die Felder in der Payload (`name``year`, und) zurück und `author` sonst nichts:

```
{
  "data": {
    "getBook": {
      "name": "Anna Karenina",
      "year": "1878",
      "author": "Leo Tolstoy",
    }
  }
}
```

Aufgrund dieses Entwurfsprinzips beseitigt GraphQL die ständigen Probleme des Über- und Unterabrufs, mit denen REST in komplexen Systemen zu APIs kämpfen hat. Dies führt zu einer effizienteren Datenerfassung und einer verbesserten Netzwerkleistung.

## Hierarchical (Hierarchisch)
<a name="hierarchical-property"></a>

GraphQL ist insofern flexibel, als die angeforderten Daten vom Benutzer an die Bedürfnisse der Anwendung angepasst werden können. Die angeforderten Daten folgen immer den Typen und der Syntax der in Ihrer GraphQL-API definierten Eigenschaften. Der folgende Ausschnitt zeigt beispielsweise den `getBook` Vorgang mit einem neuen Feldbereich namens, der alle gespeicherten Anführungszeichenfolgen und Seiten zurückgibt`quotes`, die mit dem verknüpft sind: `Book` *9780199536061*

```
{
  getBook(id: "9780199536061") {
    name
    year
    author
    quotes {
      description
      page
    }
  }
}
```

Das Ausführen dieser Abfrage gibt das folgende Ergebnis zurück:

```
{
  "data": {
    "getBook": {
      "name": "Anna Karenina",
      "year": "1878",
      "author": "Leo Tolstoy",
      "quotes": [
         {
            "description": "The highest Petersburg society is essentially one: in it everyone knows everyone else, everyone even visits everyone else.",
            "page": 135
         },
         { 
            "description": "Happy families are all alike; every unhappy family is unhappy in its own way.",
            "page": 1
         },
         {        
            "description": "To Konstantin, the peasant was simply the chief partner in their common labor.",
            "page": 251
         }
      ]
    }
  }
}
```

Wie Sie sehen können, wurden die mit dem angeforderten Buch verknüpften `quotes` Felder als Array im gleichen Format zurückgegeben, das in unserer Abfrage beschrieben wurde. Obwohl es hier nicht gezeigt wurde, hat GraphQL den zusätzlichen Vorteil, dass es nicht genau weiß, wo sich die abgerufenen Daten befinden. `Books`und `quotes` könnte separat gespeichert werden, aber GraphQL ruft die Informationen trotzdem ab, solange die Zuordnung besteht. Das bedeutet, dass Ihre Abfrage eine Vielzahl von eigenständigen Daten in einer einzigen Anfrage abrufen kann.

## Introspektiv
<a name="introspective-property"></a>

GraphQL ist selbstdokumentierend oder introspektiv. Es unterstützt mehrere integrierte Operationen, mit denen Benutzer die zugrunde liegenden Typen und Felder innerhalb des Schemas anzeigen können. Hier ist zum Beispiel ein `Foo` Typ mit einem `date` `description` Und-Feld:

```
type Foo {
	date: String
	description: String
}
```

Wir könnten die `_type` Operation verwenden, um die Typisierungsmetadaten unter dem Schema zu finden:

```
{
  __type(name: "Foo") {
    name                   # returns the name of the type
    fields {               # returns all fields in the type
      name                 # returns the name of each field
      type {               # returns all types for each field
        name               # returns the scalar type
      }
    }
  }
}
```

Dies wird eine Antwort zurückgeben:

```
{
  "__type": {
    "name": "Foo",                     # The type name
    "fields": [
      {
        "name": "date",                # The date field
        "type": { "name": "String" }   # The date's type
      },
      {
        "name": "description",         # The description field
        "type": { "name": "String" }   # The description's type
      },
    ]
  }
}
```

Diese Funktion kann verwendet werden, um herauszufinden, welche Typen und Felder ein bestimmtes GraphQL-Schema unterstützt. GraphQL unterstützt eine Vielzahl dieser introspektiven Operationen. [Weitere Informationen finden Sie unter Introspektion.](https://graphql.org/learn/introspection/)

## Starkes Tippen
<a name="strong-typing-property"></a>

GraphQL unterstützt starke Typisierung durch sein Typen- und Feldsystem. Wenn Sie etwas in Ihrem Schema definieren, muss es einen Typ haben, der vor der Laufzeit validiert werden kann. Es muss auch der Syntaxspezifikation von GraphQL entsprechen. Dieses Konzept unterscheidet sich nicht von der Programmierung in anderen Sprachen. Hier ist zum Beispiel der `Foo` Typ von früher:

```
type Foo {
	date: String
	description: String
}
```

Wir können sehen, dass das das Objekt `Foo` ist, das erstellt wird. In einer Instanz von `Foo` wird es ein `date` `description` Und-Feld geben, beide vom `String` primitiven Typ (Skalar). Syntaktisch gesehen sehen wir, dass das deklariert `Foo` wurde und dass seine Felder innerhalb seines Gültigkeitsbereichs existieren. Diese Kombination aus Typprüfung und logischer Syntax stellt sicher, dass Ihre GraphQL-API übersichtlich und selbstverständlich ist. [Die Typisierungs- und Syntaxspezifikation von GraphQL finden Sie hier.](https://spec.graphql.org/)