10 minutes
API GraphQL
Learn about the GraphQL Query API used in The Graph.
What is GraphQL?
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
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.
Ejemplos
Query for a single Token
entity defined in your schema:
{ token(id: "1") { id owner }}
Note: When querying for a single entity, the id
field is required, and it must be written as a string.
Query all Token
entities:
{ tokens { id owner }}
Clasificación
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 ordesc
for descending.
Ejemplo
{ tokens(orderBy: price, orderDirection: asc) { id owner }}
Ejemplo de filtrado de entidades anidadas
As of Graph Node v0.30.0
entities can be sorted on the basis of nested entities.
The following example shows tokens sorted by the name of their owner:
{ tokens(orderBy: owner__name, orderDirection: asc) { id owner { name } }}
Currently, you can sort by one-level deep String
or ID
types on @entity
and @derivedFrom
fields. Unfortunately, sorting by interfaces on one level-deep entities, sorting by fields which are arrays and nested entities is not yet supported.
Paginación
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.
- The default sort order is by
- Use the
skip
parameter to skip entities and paginate. For instance,first:100
shows the first 100 entities andfirst: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.
Example using first
Consulta los primeros 10 tokens:
{ tokens(first: 10) { id owner }}
To query for groups of entities in the middle of a collection, the skip
parameter may be used in conjunction with the first
parameter to skip a specified number of entities starting at the beginning of the collection.
Example using first
and skip
Query 10 Token
entities, offset by 10 places from the beginning of the collection:
{ tokens(first: 10, skip: 10) { id owner }}
Example using first
and id_ge
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.
Filtrado
- You can use the
where
parameter in your queries to filter for different properties. - You can filter on multiple values within the
where
parameter.
Example using where
Query challenges with failed
outcome:
{ challenges(where: { outcome: "failed" }) { challenger outcome application { id } }}
You can use suffixes like _gt
, _lte
for value comparison:
Ejemplo de filtrado de rango
{ applications(where: { deposit_gt: "10000000000" }) { id whitelisted deposit }}
Ejemplo de filtrado de bloques
You can also filter entities that were updated in or after a specified block with _change_block(number_gte: Int)
.
Esto puede ser útil si buscas obtener solo las entidades que han cambiado, por ejemplo, desde la última vez que realizaste una encuesta. O, alternativamente, puede ser útil para investigar o depurar cómo cambian las entidades en tu subgrafo (si se combina con un filtro de bloque, puedes aislar solo las entidades que cambiaron en un bloque específico).
{ applications(where: { _change_block: { number_gte: 100 } }) { id whitelisted deposit }}
Ejemplo de filtrado de entidades anidadas
Filtering on the basis of nested entities is possible in the fields with the _
suffix.
Esto puede ser útil si estás buscando obtener solo entidades cuyas entidades de nivel inicial cumplan con las condiciones proporcionadas.
{ challenges(where: { application_: { id: 1 } }) { challenger outcome application { id } }}
Operadores lógicos
As of Graph Node v0.30.0
you can group multiple parameters in the same where
argument using the and
or the or
operators to filter results based on more than one criteria.
AND
Operator
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: You can simplify the above query by removing the and
operator by passing a sub-expression separated by commas.
{ challenges(where: { number_gte: 100, outcome: "succeeded" }) { challenger outcome application { id } }}
OR
Operator
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 } }}
Note: When constructing queries, it is important to consider the performance impact of using the or
operator. While or
can be a useful tool for broadening search results, it can also have significant costs. One of the main issues with or
is that it can cause queries to slow down. This is because or
requires the database to scan through multiple indexes, which can be a time-consuming process. To avoid these issues, it is recommended that developers use and operators instead of or whenever possible. This allows for more precise filtering and can lead to faster, more accurate queries.
Todos los filtros
Lista completa de sufijos de parámetros:
__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
Please note that some suffixes are only supported for specific types. For example, Boolean
only supports _not
, _in
, and _not_in
, but _
is available only for object and interface types.
In addition, the following global filters are available as part of where
argument:
_change_block(number_gte: Int)
Consultas sobre Time-travel
You can query the state of your entities not just for the latest block, which is the default, but also for an arbitrary block in the past. The block at which a query should happen can be specified either by its block number or its block hash by including a block
argument in the toplevel fields of queries.
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.
Ejemplo
{ challenges(block: { number: 8000000 }) { challenger outcome application { id } }}
This query will return Challenge
entities, and their associated Application
entities, as they existed directly after processing block number 8,000,000.
Ejemplo
{ challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) { challenger outcome application { id } }}
This query will return Challenge
entities, and their associated Application
entities, as they existed directly after processing the block with the given hash.
Consultas de Búsqueda de Texto Completo
Fulltext search query fields provide an expressive text search API that can be added to the subgraph schema and customized. Refer to Defining Fulltext Search Fields to add fulltext search to your subgraph.
Fulltext search queries have one required field, text
, for supplying search terms. Several special fulltext operators are available to be used in this text
search field.
Operadores de búsqueda de texto completo:
Símbolo | Operador | Descripción |
---|---|---|
& | And | Para combinar varios términos de búsqueda en un filtro para entidades que incluyen todos los términos proporcionados |
| | Or | Las consultas con varios términos de búsqueda separados por o el operador devolverá todas las entidades que coincidan con cualquiera de los términos proporcionados |
<-> | Follow by | Especifica la distancia entre dos palabras. |
:* | Prefix | Utilice el término de búsqueda del prefijo para encontrar palabras cuyo prefijo coincida (se requieren 2 caracteres.) |
Ejemplos
Using the or
operator, this query will filter to blog entities with variations of either “anarchism” or “crumpet” in their fulltext fields.
{ blogSearch(text: "anarchism | crumpets") { id title body author }}
The follow by
operator specifies a words a specific distance apart in the fulltext documents. The following query will return all blogs with variations of “decentralize” followed by “philosophy”
{ blogSearch(text: "decentralized <-> philosophy") { id title body author }}
Combina operadores de texto completo para crear filtros más complejos. Con un operador de búsqueda de pretexto combinado con una consulta de seguimiento de este ejemplo, se buscarán coincidencias con todas las entidades del blog con palabras que comiencen con “lou” seguido de “music”.
{ blogSearch(text: "lou:* <-> music") { id title body author }}
Validación
Graph Node implements specification-based validation of the GraphQL queries it receives using graphql-tools-rs, which is based on the graphql-js reference implementation. Queries which fail a validation rule do so with a standard error - visit the GraphQL spec to learn more.
Esquema
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 Language (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.
Entidades
All GraphQL types with @entity
directives in your schema will be treated as entities and must have an ID
field.
Note: Currently, all types in your schema must have an @entity
directive. In the future, we will treat types without an @entity
directive as value objects, but this is not yet supported.
Metadatos del subgrafo
All subgraphs have an auto-generated _Meta_
object, which provides access to subgraph metadata. This can be queried as follows:
{ _meta(block: { number: 123987 }) { block { number hash timestamp } deployment hasIndexingErrors }}
Si se proporciona un bloque, los metadatos corresponden a ese bloque; de lo contrario, se utiliza el bloque indexado más reciente. Si es proporcionado, el bloque debe ser posterior al bloque de inicio del subgrafo y menor o igual que el bloque indexado más reciente.
deployment
is a unique ID, corresponding to the IPFS CID of the subgraph.yaml
file.
block
provides information about the latest block (taking into account any block constraints passed to _meta
):
- hash: el hash del bloque
- número: el número de bloque
- timestamp: la marca de tiempo del bloque, en caso de estar disponible (actualmente solo está disponible para subgrafos que indexan redes EVM)
hasIndexingErrors
is a boolean identifying whether the subgraph encountered indexing errors at some past block