subgraphs > Querying > API GraphQL

API GraphQL

Reading time: 10 min

Learn about the GraphQL Query API used in The Graph.

What is GraphQL?

Enlace a esta sección

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

Enlace a esta sección

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.

Consulta por un solo Token definido en tu esquema:

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

Consulta todas las entidades Token:

{
tokens {
id
owner
}
}

Clasificación

Enlace a esta secció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 or desc for descending.
{
tokens(orderBy: price, orderDirection: asc) {
id
owner
}
}

Ejemplo de filtrado de entidades anidadas

Enlace a esta sección

A partir de Graph Node v0.30.0, las entidades se pueden ordenar con base en entidades anidadas.

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

{
tokens(orderBy: owner__name, orderDirection: asc) {
id
owner {
name
}
}
}

Actualmente, puedes ordenar por tipos String o ID de un solo nivel en campos @entity y @derivedFrom. Desafortunadamente, aún no se admite la ordenación por interfaces en entidades de un solo nivel, la ordenación por campos que son matrices y entidades anidadas.

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.

Ejemplo usando first

Enlace a esta sección

Consulta los primeros 10 tokens:

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

Para consultar grupos de entidades en medio de una colección, el parámetro skip puede utilizarse junto con el parámetro first para omitir un número determinado de entidades empezando por el principio de la colección.

Ejemplo usando first y skip

Enlace a esta sección

Consulta 10 entidades Token, desplazadas 10 lugares desde el principio de la colección:

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

Ejemplo usando first y id_ge

Enlace a esta sección

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.

Ejemplo usando where

Enlace a esta sección

Desafíos de consulta con resultado failed:

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

Puedes utilizar sufijos como _gt, _lte para la comparación de valores:

Ejemplo de filtrado de rango

Enlace a esta sección
{
applications(where: { deposit_gt: "10000000000" }) {
id
whitelisted
deposit
}
}

Ejemplo de filtrado de bloques

Enlace a esta sección

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

Enlace a esta sección

El filtrado basado en entidades anidadas es posible en los campos con el sufijo _.

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

Enlace a esta sección

A partir de Graph Node v0.30.0 puedes agrupar múltiples parámetros en el mismo argumento where utilizando los operadores and o or para filtrar los resultados en base a más de 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
}
}
}

Azúcar sintáctico: Puedes simplificar la consulta anterior eliminando el operador and pasando una subexpresión separada por comas.

{
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: Al construir consultas, es importante considerar el impacto en el rendimiento al utilizar el operador or. Si bien or puede ser una herramienta útil para ampliar los resultados de búsqueda, también puede tener costos significativos. Uno de los principales problemas con or es que puede hacer que las consultas se vuelvan más lentas. Esto se debe a que or requiere que la base de datos escanee múltiples índices, lo que puede ser un proceso que consume tiempo. Para evitar estos problemas, se recomienda que los desarrolladores utilicen los operadores and en lugar de or siempre que sea posible. Esto permite un filtrado más preciso y puede llevar a consultas más rápidas y precisas.

Todos los filtros

Enlace a esta sección

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

Ten en cuenta que algunos sufijos solo se admiten para tipos específicos. Por ejemplo, Boolean solo admite _not, _in y _not_in, pero _ está disponible solo para tipos de objeto e interfaz.

Además, los siguientes filtros globales están disponibles como parte del argumento where:

_change_block(number_gte: Int)

Consultas sobre Time-travel

Enlace a esta sección

Puedes consultar el estado de tus entidades no solo para el último bloque, que es el predeterminado, sino también para un bloque arbitrario en el pasado. El bloque en el que debe ocurrir una consulta se puede especificar por su número de bloque o su hash de bloque al incluir un argumento block en los campos de nivel superior de las consultas.

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
}
}
}

Esta consulta devolverá entidades Challenge y sus entidades Application asociadas, tal como existían directamente después de procesar el bloque número 8,000,000.

{
challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {
challenger
outcome
application {
id
}
}
}

Esta consulta devolverá entidades Challenge y sus entidades Application asociadas, tal como existían directamente después de procesar el bloque con el hash dado.

Consultas de Búsqueda de Texto Completo

Enlace a esta sección

Los campos de consulta de búsqueda de texto completo proporcionan una API de búsqueda de texto expresivo que se puede agregar al esquema del subgrafo y personalizar. Consulta Defining Fulltext Search Fields para agregar búsqueda de texto completo a tu subgrafo.

Las consultas de búsqueda de texto completo tienen un campo obligatorio, text, para proporcionar términos de búsqueda. Hay varios operadores especiales de texto completo disponibles para usar en este campo de búsqueda text.

Operadores de búsqueda de texto completo:

SímboloOperadorDescripción
&AndPara combinar varios términos de búsqueda en un filtro para entidades que incluyen todos los términos proporcionados
|OLas 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 byEspecifica la distancia entre dos palabras.
:*PrefijoUtilice el término de búsqueda del prefijo para encontrar palabras cuyo prefijo coincida (se requieren 2 caracteres.)

Con el operador or, esta consulta filtrará las entidades de blog con variaciones de "anarchism" o "crumpet" en sus campos de texto completo.

{
blogSearch(text: "anarchism | crumpets") {
id
title
body
author
}
}

El operador follow by especifica palabras separadas por una distancia específica en los documentos de texto completo. La siguiente consulta devolverá todos los blogs con variaciones de "decentralize" seguido por "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
}
}

Graph Node implementa una validación basada en especificaciones de las consultas de GraphQL que recibe mediante [graphql-tools-rs](https:// github.com/dotansimha/graphql-tools-rs#validation-rules), que se basa en [implementación de referencia de graphql-js](https://github.com/graphql/graphql-js /tree/main/src/validation). Las consultas que fallan en una regla de validación lo hacen con un error estándar: visita las especificaciones de GraphQL para obtener más información.

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.

Todos los tipos de GraphQL con directivas @entity en tu esquema se tratarán como entidades y deben tener un campo ID.

Nota: Actualmente, todos los tipos en tu esquema deben tener una directiva @entity. En el futuro, trataremos los tipos sin una directiva @entity como objetos de valor, pero esto aún no se admite.

Metadatos del subgrafo

Enlace a esta sección

Todos los subgrafos tienen un objeto _Meta_ generado automáticamente, que brinda acceso a los metadatos del subgrafo. Esto se puede consultar de la siguiente manera:

{
_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 es un ID único, correspondiente al IPFS CID del archivo subgraph.yaml.

block proporciona información sobre el último bloque (teniendo en cuenta cualquier restricción de bloque pasada a _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 es un valor booleano que identifica si el subgrafo encontró errores de indexación en algún bloque anterior

Editar página

Anterior
Sistemas Distribuidos
Siguiente
Subgraph ID vs Deployment ID
Editar página