subgraphs > Querying > API GraphQL

API GraphQL

Reading time: 10 min

Learn about the GraphQL Query API used in The Graph.

What is GraphQL?

Collegamento a questa sezione

GraphQL is a query language for APIs and a runtime for executing those queries with your existing data. The Graph uses GraphQL to query subgraphs.

To understand the larger role that GraphQL plays, review developing and creating a subgraph.

Queries with GraphQL

Collegamento a questa sezione

In your subgraph schema you define types called Entities. For each Entity type, entity and entities fields will be generated on the top-level Query type.

Note: query does not need to be included at the top of the graphql query when using The Graph.

Eseguire query di una singola entità Token definita nello schema:

{
token(id: "1") {
id
owner
}
}

Note: When querying for a single entity, the id field is required, and it must be writen as a string.

Eseguire query di tutte le entità Token:

{
tokens {
id
owner
}
}

When querying a collection, you may:

  • Use the orderBy parameter to sort by a specific attribute.
  • Use the orderDirection to specify the sort direction, asc for ascending or desc for descending.
{
tokens(orderBy: price, orderDirection: asc) {
id
owner
}
}

Esempio di ordinamento di entità annidate

Collegamento a questa sezione

A partire da Graph Node v0.30.0 le entità possono essere ordinate sulla base delle entità annidate.

The following example shows tokens sorted by the name of their owner:

{
tokens(orderBy: owner__name, orderDirection: asc) {
id
owner {
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 interfacce su entità profonde un livello, l'ordinamento per campi che sono array e entità annidate.

When querying a collection, it's best to:

  • Use the first parameter to paginate from the beginning of the collection.
    • The default sort order is by ID in ascending alphanumeric order, not by creation time.
  • Use the skip parameter to skip entities and paginate. For instance, first:100 shows the first 100 entities and first:100, skip:100 shows the next 100 entities.
  • Avoid using skip values in queries because they generally perform poorly. To retrieve a large number of items, it's best to page through entities based on an attribute as shown in the previous example above.

Esempio di utilizzo di first

Collegamento a questa sezione

Eseguire query di primi 10 token:

{
tokens(first: 10) {
id
owner
}
}

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.

Esempio di utilizzo di first e skip

Collegamento a questa sezione

Eseguire query di 10 entità Token, sfalsate di 10 posizioni rispetto all'inizio della collezione:

{
tokens(first: 10, skip: 10) {
id
owner
}
}

Esempio di utilizzo di first e id_ge

Collegamento a questa sezione

If a client needs to retrieve a large number of entities, it's more performant to base queries on an attribute and filter by that attribute. For example, a client could retrieve a large number of tokens using this query:

query manyTokens($lastID: String) {
tokens(first: 1000, where: { id_gt: $lastID }) {
id
owner
}
}

The first time, it would send the query with lastID = "", and for subsequent requests it would set lastID to the id attribute of the last entity in the previous request. This approach will perform significantly better than using increasing skip values.

  • You can use the where parameter in your queries to filter for different properties.
  • You can filter on multiple values within the where parameter.

Esempio di utilizzo di where

Collegamento a questa sezione

Query con esito failed:

{
challenges(where: { outcome: "failed" }) {
challenger
outcome
application {
id
}
}
}

È possibile utilizzare suffissi come _gt, _lte per confrontare i valori:

Esempio di filtraggio dell'intervallo

Collegamento a questa sezione
{
applications(where: { deposit_gt: "10000000000" }) {
id
whitelisted
deposit
}
}

Esempio di filtraggio dei blocchi

Collegamento a questa sezione

You can also filter entities that were updated in or after a specified block with _change_block(number_gte: Int).

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 } }) {
id
whitelisted
deposit
}
}

Esempio di filtraggio di entità annidate

Collegamento a questa sezione

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 } }) {
challenger
outcome
application {
id
}
}
}

A partire dalla versione Graph Node v0.30.0 è 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.

The following example filters for challenges with outcome succeeded and number greater than or equal to 100.

{
challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
challenger
outcome
application {
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" }) {
challenger
outcome
application {
id
}
}
}

The following example filters for challenges with outcome succeeded or number greater than or equal to 100.

{
challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
challenger
outcome
application {
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)

Query Time-travel

Collegamento a questa sezione

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

The result of such a query will not change over time, i.e., querying at a certain past block will return the same result no matter when it is executed, with the exception that if you query at a block very close to the head of the chain, the result might change if that block turns out to not be on the main chain and the chain gets reorganized. Once a block can be considered final, the result of the query will not change.

Note: The current implementation is still subject to certain limitations that might violate these guarantees. The implementation can not always tell that a given block hash is not on the main chain at all, or if a query result by a block hash for a block that is not yet considered final could be influenced by a block reorganization running concurrently with the query. They do not affect the results of queries by block hash when the block is final and known to be on the main chain. This issue explains what these limitations are in detail.

{
challenges(block: { number: 8000000 }) {
challenger
outcome
application {
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" }) {
challenger
outcome
application {
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.

Query di ricerca fulltext

Collegamento a questa sezione

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 Defining Fulltext Search Fields 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:

SimboloOperatoreDescrizione
&AndPer combinare più termini di ricerca in un filtro per le entità che includono tutti i termini forniti
|OrLe query con più termini di ricerca separati dall'operatore Or restituiranno tutte le entità con una corrispondenza tra i termini forniti
<->Follow bySpecifica la distanza tra due parole.
:*PrefissoUtilizzare 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") {
id
title
body
author
}
}

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") {
id
title
body
author
}
}

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") {
id
title
body
author
}
}

Graph Node implementa la validazione basata sulle specifiche delle query GraphQL che riceve utilizzando graphql-tools-rs, che si basa sull'implementazione di riferimento di graphql-js. Le query che non rispettano una regola di validazione vengono segnalate con un errore standard - per saperne di più, visitare le specifiche di GraphQL.

The schema of your dataSources, i.e. the entity types, values, and relationships that are available to query, are defined through the GraphQL Interface Definition Langauge (IDL).

GraphQL schemas generally define root types for queries, subscriptions and mutations. The Graph only supports queries. The root Query type for your subgraph is automatically generated from the GraphQL schema that's included in your subgraph manifest.

Note: Our API does not expose mutations because developers are expected to issue transactions directly against the underlying blockchain from their applications.

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.

Metadati del Subgraph

Collegamento a questa sezione

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 {
number
hash
timestamp
}
deployment
hasIndexingErrors
}
}

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

Modifica pagina

Precedente
Sistemi distribuiti
Successivo
Subgraph ID vs Deployment ID
Modifica pagina