Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Interfacce e unioni in GraphQL
Il sistema di tipo GraphQL supportaInterfacce
Il sistema di tipo GraphQL supporta ancheSindacati
La sezione seguente è un riferimento per la digitazione dello schema.
Esempi di interfacce
Potremmo rappresentare unEvent
interfaccia che rappresenta qualsiasi tipo di attività o incontro di persone. Alcuni tipi di eventi possibili sonoConcert
,Conference
, eFestival
. Questi tipi condividono tutti caratteristiche comuni, in quanto hanno tutti un nome, un luogo in cui avviene l'evento e una data di inizio e una di fine. Anche questi tipi presentano delle differenze; aConference
offre un elenco di relatori e workshop, mentre aConcert
presenta una band che si esibisce.
In Schema Definition Language (SDL), ilEvent
l'interfaccia è definita come segue:
interface Event { id: ID! name : String! startsAt: String endsAt: String venue: Venue minAgeRestriction: Int }
E ciascuno dei tipi implementa ilEvent
interfaccia come segue:
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] }
Le interfacce sono utili per rappresentare elementi che possono essere di diversi tipi. Ad esempio, possiamo cercare tutti gli eventi che avvengono in un luogo specifico. Aggiungiamo un campo findEventsByVenue
allo schema come segue:
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] }
IlfindEventsByVenue
restituisce un elenco diEvent
. Poiché i campi dell'interfaccia GraphQL sono comuni a tutti i tipi di implementazione, è possibile selezionare qualsiasi campo nell'interfaccia Event
(id
, name
, startsAt
, endsAt
, venue
e minAgeRestriction
). Inoltre, puoi accedere ai campi in qualsiasi tipo di implementazione utilizzando frammenti
Esaminiamo un esempio di query GraphQL che utilizza l'interfaccia.
query { findEventsAtVenue(venueId: "Madison Square Garden") { id name minAgeRestriction startsAt ... on Festival { performers } ... on Concert { performingBand } ... on Conference { speakers workshops } } }
La query precedente produce un singolo elenco di risultati e il server può, per impostazione predefinita, ordinare gli eventi in base alla data di inizio.
{ "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" ] } ] } }
Poiché i risultati vengono restituiti come una singola raccolta di eventi, l'utilizzo di interfacce per rappresentare caratteristiche comuni è molto utile per l'ordinamento dei risultati.
Esempi di unione
Come affermato in precedenza, i sindacati non definiscono insiemi di campi comuni. Un risultato di ricerca potrebbe rappresentare molti tipi diversi. Utilizzando lo schema Event
, è possibile definire un'unione SearchResult
come segue:
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 questo caso, per interrogare qualsiasi campo sul nostroSearchResult
union, devi usare i frammenti:
query { search(query: "Madison") { ... on Venue { id name address } ... on Festival { id name performers } ... on Concert { id name performingBand } ... on Conference { speakers workshops } } }
Digita la risoluzione inAWS AppSync
La risoluzione dei tipi è il meccanismo attraverso il quale il motore GraphQL identifica un valore risolto come tipo di oggetto specifico.
Tornando all'esempio della ricerca sindacale, a condizione che la nostra query abbia prodotto risultati, ogni elemento nell'elenco dei risultati deve presentarsi come uno dei possibili tipi diSearchResult
unione definita (cioè,Conference
,Festival
,Concert
, oppureVenue
).
Poiché la logica per identificare un tipo Festival
rispetto a un tipo Venue
o Conference
dipende dai requisiti dell'applicazione, il motore GraphQL deve ricevere un suggerimento per identificare i possibili tipi dai risultati non elaborati.
ConAWS AppSync, questo suggerimento è rappresentato da un metacampo denominato__typename
, il cui valore corrisponde al nome del tipo di oggetto identificato.__typename
è obbligatorio per i tipi restituiti che sono interfacce o unioni.
Esempio di risoluzione dei tipi
Ora, riutilizzeremo lo schema precedente. Puoi continuare passando alla console e aggiungendo il codice seguente nella pagina Schema:
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 }
Colleghiamo un resolver al campo Query.search
. NelResolvers
sezione, scegliAllega, crea un nuovoFonte di datidi tipoNESSUNA, e poi dargli un nomeStubDataSource. Ai fini di questo esempio, fingeremo di aver recuperato i risultati da un'origine esterna e di aver codificato tali risultati nel modello di mappatura della richiesta.
Nel riquadro del modello di mappatura della richiesta immetti i seguenti dati:
{ "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"] } ] }
Se l'applicazione restituisce il nome del tipo come parte diid
campo, la logica di risoluzione dei tipi deve analizzare ilid
campo per estrarre il nome del tipo e quindi aggiungere il__typename
campo per ciascuno dei risultati. È possibile eseguire la logica nel modello di mappatura della risposta come segue:
Nota
Puoi eseguire questa attività anche come parte della tua funzione Lambda, se utilizzi l'origine dati Lambda.
#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)
Eseguire la seguente query:
query { search(query: "Madison") { ... on Venue { id name address } ... on Festival { id name performers } ... on Concert { id name performingBand } ... on Conference { speakers workshops } } }
La query restituisce i seguenti risultati:
{ "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" ] } ] } }
La logica di risoluzione dei tipi varia a seconda dell'applicazione. Ad esempio, puoi definire una logica di identificazione diversa che controlla l'esistenza di determinati campi o addirittura una combinazione di campi. Ovvero, puoi rilevare la presenza del campo performers
per identificare un tipo Festival
o la combinazione dei campi speakers
e workshops
per identificare un tipo Conference
. In definitiva, sta a te definire la logica che desideri utilizzare.