

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.

# Schnittstellen und Unions in GraphQL
<a name="interfaces-and-unions"></a>

Das GraphQL-Typsystem unterstützt [Schnittstellen](https://graphql.org/learn/schema/#interfaces). Eine Schnittstelle stellt eine bestimmte Gruppe von Feldern dar, die ein Typ umfassen muss, um die Schnittstelle zu implementieren. 

Das GraphQL-Typsystem unterstützt auch [Unions](https://graphql.org/learn/schema/#union-types). Vereinigungen sind weitgehend identisch mit Schnittstellen, definieren aber keinen gemeinsamen Satz von Feldern. Vereinigungen werden in der Regel gegenüber Schnittstellen bevorzugt, wenn die möglichen Typen keine gemeinsame logische Hierarchie besitzen.

Der folgende Abschnitt ist eine Referenz für die Schematypisierung.

## Beispiele für Benutzeroberflächen
<a name="interfaces"></a>

Wir könnten eine `Event` Schnittstelle darstellen, die jede Art von Aktivität oder Zusammenkunft von Menschen darstellt. Einige mögliche Ereignistypen sind `Concert``Conference`,, und`Festival`. All diese Typen haben gemeinsame Merkmale: Name, Veranstaltungsort sowie Start- und Enddatum. Auch bei diesen Typen gibt es Unterschiede. Bei einer `Conference` handelt es sich um eine Liste von Rednern und Workshops, bei `Concert` einer tritt eine Band auf.

In der Schema Definition Language (SDL) ist die `Event` Schnittstelle wie folgt definiert:

```
interface Event {
        id: ID!
        name : String!
        startsAt: String
        endsAt: String
        venue: Venue
        minAgeRestriction: Int
}
```

Und jeder der Typen implementiert die `Event` Schnittstelle wie folgt:

```
type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

Schnittstellen sind nützlich zur Darstellung von Elementen, die in Form unterschiedlicher Typen auftreten können. Zum Beispiel könnten wir nach allen Ereignissen an einem bestimmten Veranstaltungsort suchen. Fügen wir nun folgendermaßen ein `findEventsByVenue`-Feld zum Schema hinzu:

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
}

type Venue {
    id: ID!
    name: String
    address: String
    maxOccupancy: Int
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

Das `findEventsByVenue` gibt eine Liste von zurück`Event`. Da GraphQL-Schnittstellenfelder von allen Implementierungstypen verwendet werden, können Sie jedes beliebige Feld der `Event`-Schnittstelle auswählen (`id`, `name`, `startsAt`, `endsAt`, `venue` und `minAgeRestriction`). Alternativ können Sie mit GraphQL-[Fragmenten](https://graphql.org/learn/queries/#fragments) auf die Felder jedes Implementierungstyps zugreifen, sofern Sie den Typ angeben.

Schauen wir uns ein Beispiel für eine GraphQL-Abfrage an, die die Schnittstelle verwendet.

```
query {
  findEventsAtVenue(venueId: "Madison Square Garden") {
    id
    name
    minAgeRestriction
    startsAt

    ... on Festival {
      performers
    }

    ... on Concert {
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

Die vorherige Abfrage gibt eine einzige Ergebnisliste aus und der Server kann die Ereignisse standardmäßig nach Startdatum sortieren.

```
{
  "data": {
    "findEventsAtVenue": [
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "minAgeRestriction": 21,
        "startsAt": "2018-10-05T14:48:00.000Z",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "minAgeRestriction": 18,
        "startsAt": "2018-10-07T14:48:00.000Z",
        "performingBand": "The Jumpers"
      },
      {
        "id": "Conference-4",
        "name": "Conference 4",
        "minAgeRestriction": null,
        "startsAt": "2018-10-09T14:48:00.000Z",
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

Da Ergebnisse als eine einzelne Sammlung von Ereignissen zurückgegeben werden, ist die Verwendung von Schnittstellen zur Darstellung gemeinsamer Merkmale für die Sortierung der Ergebnisse sehr hilfreich.

## Beispiele für Vereinigungen
<a name="unions"></a>

Wie bereits erwähnt, definieren Gewerkschaften keine gemeinsamen Feldgruppen. Ein Suchergebnis kann viele verschiedene Typen repräsentieren. Mit dem `Event`-Schema können Sie eine `SearchResult`-Vereinigung definieren. Gehen Sie wie folgt vor:

```
type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue
```

In diesem Fall müssen Sie Fragmente verwenden, um ein beliebiges Feld in unserer `SearchResult` Union abzufragen:

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
      id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

## Geben Sie Auflösung ein AWS AppSync
<a name="type-resolution-in-appsynclong"></a>

Die Typenauflösung ist der Mechanismus, durch den die GraphQL-Engine einen aufgelösten Wert als bestimmten Objekttyp identifiziert.

Zurück zum Beispiel für die Union-Suche: Vorausgesetzt, dass unsere Abfrage Ergebnisse liefert, muss jedes Element in der Ergebnisliste als einer der möglichen Typen dargestellt werden, die von der `SearchResult` Union definiert wurden (d. h.`Conference`,, `Festival``Concert`, oder`Venue`).

Da die Logik zum Unterscheiden zwischen `Festival`, `Venue` und `Conference` von den Anwendungsanforderungen abhängt, muss die GraphQL-Engine Informationen erhalten, um unsere möglichen Typen in den Raw-Ergebnissen zu identifizieren.

Mit AWS AppSync wird dieser Hinweis durch ein Metafeld mit dem Namen dargestellt`__typename`, dessen Wert dem Namen des identifizierten Objekttyps entspricht. `__typename`ist für Rückgabetypen erforderlich, bei denen es sich um Interfaces oder Unions handelt.

## Beispiel für die Typauflösung
<a name="type-resolution-example"></a>

Verwenden wir erneut das vorherige Schema. Sie können dies reproduzieren, indem Sie zur Konsole gehen und Folgendes unter der Seite **Schema** hinzufügen:

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue

type Venue {
    id: ID!
    name: String!
    address: String
    maxOccupancy: Int
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}
```

Hängen wir nun einen Resolver an das `Query.search`-Feld an. Wählen Sie in dem `Resolvers` Abschnitt **Anhängen** aus, erstellen Sie eine neue **Datenquelle** vom Typ *NONE*, und geben Sie ihr dann einen Namen *StubDataSource*. Für dieses Beispiel nehmen wir an, wir haben die Ergebnisse aus einer externen Quelle abgerufen und codieren die abgerufenen Ergebnisse fest in unserer Zuweisungsvorlage für Anforderungen.

Geben Sie im Bereich der Anforderungszuweisungsvorlage Folgendes ein:

```
{
    "version" : "2018-05-29",
    "payload":
    ## We are effectively mocking our search results for this example
    [
        {
            "id": "Venue-1",
            "name": "Venue 1",
            "address": "2121 7th Ave, Seattle, WA 98121",
            "maxOccupancy": 1000
        },
        {
            "id": "Festival-2",
            "name": "Festival 2",
            "performers": ["The Singers", "The Screamers"]
        },
        {
            "id": "Concert-3",
            "name": "Concert 3",
            "performingBand": "The Jumpers"
        },
        {
            "id": "Conference-4",
            "name": "Conference 4",
            "speakers": ["The Storytellers"],
            "workshops": ["Writing", "Reading"]
        }
    ]
}
```

Wenn die Anwendung den Typnamen als Teil des `id` Felds zurückgibt, muss die Typauflösungslogik das `id` Feld analysieren, um den Typnamen zu extrahieren, und dann das `__typename` Feld zu jedem der Ergebnisse hinzufügen. Sie können die Logik in der Antwortzuweisungsvorlage folgendermaßen umsetzen:

**Anmerkung**  
Sie können diese Aufgabe auch als Teil Ihrer Lambda-Funktion ausführen, wenn Sie die Lambda-Datenquelle verwenden.

```
#foreach ($result in $context.result)
    ## Extract type name from the id field.
    #set( $typeName = $result.id.split("-")[0] )
    #set( $ignore = $result.put("__typename", $typeName))
#end
$util.toJson($context.result)
```

Führen Sie die folgende Abfrage aus:

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
        id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

Die Abfrage liefert die folgenden Ergebnisse:

```
{
  "data": {
    "search": [
      {
        "id": "Venue-1",
        "name": "Venue 1",
        "address": "2121 7th Ave, Seattle, WA 98121"
      },
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "performingBand": "The Jumpers"
      },
      {
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

Die Typenauflösungslogik variiert je nach Anwendung. Sie können beispielsweise eine andere Identifizierungslogik verwenden, die prüft, ob bestimmte Felder oder auch Kombinationen von Feldern vorhanden sind. Sie können also feststellen, ob das `performers`-Feld vorhanden ist, um ein `Festival` zu identifizieren, oder die Kombination der Felder `speakers` und `workshops`, um eine `Conference` zu identifizieren. Letztlich liegt es an Ihnen, die Logik zu definieren, die Sie verwenden möchten.