API GraphQL
Reading time: 10 min
This guide explains the GraphQL Query API that is used for The Graph Protocol.
Nello schema di subgraph si definiscono tipi chiamati Entities
. Per ogni tipo di Entity
, un'entity
e un campo entities
saranno generati sul tipo Query
di livello superiore. Si noti che query
non deve essere inclusa all'inizio della query graphql
quando si usa The Graph.
Eseguire query di una singola entità Token
definita nello schema:
{token(id: "1") {idowner}}
Nota: Quando si esegue una query per una singola entità, il campo id
è obbligatorio e deve essere una stringa.
Eseguire query di tutte le entità Token
:
{tokens {idowner}}
Quando si esegue query di una collezione, il parametro orderBy
può essere usato per ordinare in base a un attributo specifico. Inoltre, l'opzione orderDirection
può essere usata per specificare la direzione dell'ordinamento, asc
per l'ascendente oppure desc
per il discendente.
{tokens(orderBy: price, orderDirection: asc) {idowner}}
A partire da Graph Node le entità possono essere ordinate sulla base delle entità annidate.
Nell'esempio seguente, ordiniamo i token in base al nome del loro proprietario:
{tokens(orderBy: owner__name, orderDirection: asc) {idowner {name}}}
Attualmente, è possibile ordinare per tipi di String
oppure ID
profondi un livello sui campi @entity
e @derivedFrom
. Purtroppo non è ancora supportato , l'ordinamento per campi che sono array e entità annidate.
Quando si esegue una query di una collezione, il parametro first
può essere usato per impaginare dall'inizio della raccolta. Va notato che l'ordinamento predefinito è per ID in ordine alfanumerico crescente, non per ora di creazione.
Inoltre, il parametro skip
può essere usato per saltare le entità ed impaginare. Ad esempio, first:100
mostra le prime 100 entità e first:100, skip:100
mostra le 100 entità successive.
Le query dovrebbero evitare di usare valori skip
molto grandi, perché in genere hanno un rendimento scarso. Per recuperare un gran numero di elementi, è molto meglio sfogliare le entità in base a un attributo, come mostrato nell'ultimo esempio.
Eseguire query di primi 10 token:
{tokens(first: 10) {idowner}}
Per eseguire query di gruppi di entità nel mezzo di una collezione, il parametro skip
può essere usato insieme al parametro first
per saltare un numero specifico di entità a partire dall'inizio della collezione.
Eseguire query di 10 entità Token
, sfalsate di 10 posizioni rispetto all'inizio della collezione:
{tokens(first: 10, skip: 10) {idowner}}
Se un client deve recuperare un gran numero di entità, è molto più performante basare le query su un attributo e filtrare in base a tale attributo. Ad esempio, un client potrebbe recuperare un gran numero di token utilizzando questa query:
query manyTokens($lastID: String) {tokens(first: 1000, where: { id_gt: $lastID }) {idowner}}
La prima volta, si invierebbe la query con lastID = ""
e per le richieste successive si imposterebbe lastID
sull'attributo id
dell'ultima entità della richiesta precedente. Questo approccio è nettamente migliore rispetto all'utilizzo di valori di skip
crescenti.
È possibile utilizzare il parametro where
nelle query per filtrare diverse proprietà. È possibile filtrare su più valori all'interno del parametro where
.
Query con esito failed
:
{challenges(where: { outcome: "failed" }) {challengeroutcomeapplication {id}}}
È possibile utilizzare suffissi come _gt
, _lte
per confrontare i valori:
{applications(where: { deposit_gt: "10000000000" }) {idwhitelisteddeposit}}
È anche possibile filtrare le entità in base al metodo _change_block(number_gte: Int)
- questo filtra le entità che sono state aggiornate nel o dopo il blocco specificato.
Questo può essere utile se si vuole recuperare solo le entità che sono cambiate, ad esempio dall'ultima volta che è stato effettuato il polling. In alternativa, può essere utile per indagare o fare il debug di come le entità stanno cambiando nel subgraph (se combinato con un filtro di blocco, è possibile isolare solo le entità che sono cambiate in un blocco specifico).
{applications(where: { _change_block: { number_gte: 100 } }) {idwhitelisteddeposit}}
Il filtraggio sulla base di entità annidate è possibile nei campi con il suffisso _
.
Questo può essere utile se si vuole recuperare solo le entità il cui livello di figlio soddisfa le condizioni fornite.
{challenges(where: { application_: { id: 1 } }) {challengeroutcomeapplication {id}}}
A partire dalla versione Graph Node è possibile raggruppare più parametri nello stesso argomento where
usando gli operatori and
oppure or
per filtrare i risultati in base a più di un criterio.
Nell'esempio seguente, si filtrano le sfide con outcome
succeeded
e number
maggiore o uguale a 100
.
{challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {challengeroutcomeapplication {id}}}
Syntactic sugar: Si può semplificare la query precedente eliminando l'operatore and
passando una sottoespressione separata da virgole.
{challenges(where: { number_gte: 100, outcome: "succeeded" }) {challengeroutcomeapplication {id}}}
Nell'esempio seguente, si filtrano le sfide con outcome
succeeded
oppure number
maggiore o uguale a 100
.
{challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {challengeroutcomeapplication {id}}}
Nota: Quando si costruiscono le query, è importante considerare l'impatto sulle prestazioni dell'uso dell'operatore or
. Sebbene or
possa essere uno strumento utile per ampliare i risultati della ricerca, può anche avere costi significativi. Uno dei problemi principali di or
è che può causare un rallentamento delle query. Questo perché or
richiede al database di eseguire la scansione di più indici, un processo che può richiedere molto tempo. Per evitare questi problemi, si consiglia agli sviluppatori di utilizzare gli operatori e al posto di o quando possibile. Ciò consente di effettuare filtri più precisi e di ottenere query più rapide e precise.
Elenco completo dei suffissi dei parametri:
__not_gt_lt_gte_lte_in_not_in_contains_contains_nocase_not_contains_not_contains_nocase_starts_with_starts_with_nocase_ends_with_ends_with_nocase_not_starts_with_not_starts_with_nocase_not_ends_with_not_ends_with_nocase
Si noti che alcuni suffissi sono supportati solo per tipi specifici. Ad esempio, Boolean
supporta solo _not
, _in
e _not_in
, mentre _
è disponibile solo per i tipi oggetto e interfaccia.
Inoltre, i seguenti filtri globali sono disponibili come parte dell'argomento where
:
_change_block(number_gte: Int)
È possibile effetuare query dello stato delle entità non solo per l'ultimo blocco, che è quello predefinito, ma anche per un blocco nel passato. Il blocco in cui deve avvenire una query può essere specificato dal suo numero di blocco o dal suo hash, includendo un argomento block
nei campi di livello superiore delle query.
Il risultato di una query di questo tipo non cambia nel tempo, cioè la query di un determinato blocco passato restituirà lo stesso risultato indipendentemente dal momento in cui viene eseguita, con l'eccezione che se si fa query di un blocco molto vicino alla testa della catena, il risultato potrebbe cambiare se quel blocco risulta non essere nella catena principale e la catena viene riorganizzata. Una volta che un blocco può essere considerato definitivo, il risultato della query non cambierà.
Si noti che l'attuale implementazione è ancora soggetta ad alcune limitazioni che potrebbero violare queste garanzie. L'implementazione non è sempre in grado di dire che un determinato block hash non è affatto presente nella chain principale, o che il risultato di una query per il block hash per un blocco che non può ancora essere considerato definitivo potrebbe essere influenzato da una riorganizzazione di blocco in corso contemporaneamente alla query. Non influiscono sui risultati delle query in base all'block hash quando il blocco è definitivo e si sa che si trova nella chain principale. è spiegato in dettaglio quali sono queste limitazioni.
{challenges(block: { number: 8000000 }) {challengeroutcomeapplication {id}}}
Questa query restituirà le entità Challenge
e le entità Application
ad esse associate, così come esistevano direttamente dopo l'elaborazione del blocco numero 8.000.000.
{challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {challengeroutcomeapplication {id}}}
Questa query restituirà le entità Challenge
e le entità Application
ad esse associate, così come esistevano direttamente dopo l'elaborazione del blocco con l'hash indicato.
I campi di ricerca fulltext forniscono un'API di ricerca testuale espressiva che può essere aggiunta allo schema del subgraph e personalizzata. Fare riferimento a per aggiungere la ricerca fulltext al subgraph.
Le query di ricerca fulltext hanno un campo obbligatorio, text
, per fornire i termini di ricerca. In questo campo di ricerca text
sono disponibili diversi operatori speciali per il fulltext.
Operatori di ricerca fulltext:
Simbolo | Operatore | Descrizione |
---|---|---|
& | And | Per combinare più termini di ricerca in un filtro per le entità che includono tutti i termini forniti |
| | Or | Le query con più termini di ricerca separati dall'operatore Or restituiranno tutte le entità con una corrispondenza tra i termini forniti |
<-> | Follow by | Specifica la distanza tra due parole. |
:* | Prefisso | Utilizzare il termine di ricerca del prefisso per trovare le parole il cui prefisso corrisponde (sono richiesti 2 caratteri.) |
Utilizzando l'operatore or
, questa query filtrerà le entità blog con variazioni di "anarchism" o "crumpet" nei loro campi fulltext.
{blogSearch(text: "anarchism | crumpets") {idtitlebodyauthor}}
L'operatore follow by
specifica le parole a una distanza specifica nei documenti fulltext. La seguente query restituirà tutti i blog con variazioni di "decentralize" seguite da "philosophy"
{blogSearch(text: "decentralized <-> philosophy") {idtitlebodyauthor}}
Combinare gli operatori fulltext per creare filtri più complessi. Con un operatore di ricerca pretext combinato con un follow by questa query di esempio corrisponderà a tutte le entità del blog con parole che iniziano con "lou" seguite da "music".
{blogSearch(text: "lou:* <-> music") {idtitlebodyauthor}}
Graph Node implementa la validazione delle query GraphQL che riceve utilizzando , che si basa sull'. Le query che non rispettano una regola di validazione vengono segnalate con un errore standard - per saperne di più, visitare le .
Lo schema dell'origine di dati-- cioè i tipi di entità, i valori e le relazioni disponibili per le query -- sono definiti attraverso .
Gli schemi GraphQL in genere definiscono i tipi di radice per le query
, le sottoscrizioni
e le mutazioni
. The Graph supporta solo le query
. Il tipo di Query
principale per il subgraph viene generato automaticamente dallo schema GraphQL incluso nel manifest del subgraph.
Nota: La nostra API non espone mutazioni perché gli sviluppatori devono emettere transazioni direttamente contro la blockchain sottostante dalle loro applicazioni.
Tutti i tipi GraphQL con direttive @entity
nello schema saranno trattati come entità e devono avere un campo ID
.
Nota: Attualmente, tutti i tipi nello schema devono avere una direttiva @entity
. In futuro, i tipi senza direttiva @entity
saranno trattati come oggetti valore, ma questo non è ancora supportato.
Tutti i subgraph hanno un oggetto _Meta_
autogenerato, che fornisce accesso ai metadati del subgraph. Questo oggetto può essere interrogato come segue:
{_meta(block: { number: 123987 }) {block {numberhashtimestamp}deploymenthasIndexingErrors}}
Se viene fornito un blocco, i metadati si riferiscono a quel blocco, altrimenti viene utilizzato il blocco indicizzato più recente. Se fornito, il blocco deve essere successivo al blocco iniziale del subgraph e inferiore o uguale al blocco indicizzato più recente.
deployment
è un ID unico, corrispondente al CID IPFS del file subgraph.yaml
.
block
fornisce informazioni sull'ultimo blocco (tenendo conto di eventuali vincoli di blocco passati a _meta
):
- hash: l'hash del blocco
- numero: il numero del blocco
- timestamp: il timestamp del blocco, se disponibile (attualmente è disponibile solo per i subgraph che indicizzano le reti EVM)
hasIndexingErrors
è un booleano che identifica se il subgraph ha incontrato errori di indicizzazione in qualche blocco passato