Consultando > API GraphQL

API GraphQL

Reading time: 10 min

Esta guía explica la API de consulta GraphQL que se utiliza para The Graph Protocol.

Consultas

Enlace a esta sección

En tu esquema de subgrafos defines tipos llamados Entities. Por cada tipo de Entity, se generará un campo entity y entities en el nivel superior del tipo Query. Ten en cuenta que no es necesario incluir query en la parte superior de la consulta graphql cuando se utiliza The Graph.

Consulta por un solo Token definido en tu esquema:

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

Nota: Cuando se consulta una sola entidad, el campo id es obligatorio y debe ser un string.

Consulta todas las entidades Token:

{
tokens {
id
owner
}
}

Clasificación

Enlace a esta sección

Al consultar una colección, el parámetro orderBy puede utilizarse para ordenar por un atributo específico. Además, el orderDirection se puede utilizar para especificar la dirección de orden, asc para ascendente o desc para descendente.

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

En el siguiente ejemplo, ordenamos los tokens por el nombre de su propietario:

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

Al consultar una colección, el parámetro first puede utilizarse para paginar desde el principio de la colección. Cabe destacar que el orden por defecto es por ID en orden alfanumérico ascendente, no por tiempo de creación.

Además, el parámetro skip puede utilizarse para saltar entidades y paginar. por ejemplo, first:100 muestra las primeras 100 entidades y first:100, skip:100 muestra las siguientes 100 entidades.

Las consultas deben evitar el uso de valores de skip muy grandes, ya que suelen tener un rendimiento deficiente. Para recuperar un gran número de elementos, es mucho mejor para paginar recorrer las entidades basándose en un atributo, como se muestra en el último ejemplo.

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

Si un cliente necesita recuperar un gran número de entidades, es mucho más eficaz basar las consultas en un atributo y filtrar por ese atributo. Por ejemplo, un cliente podría recuperar un gran número de tokens utilizando esta consulta:

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

La primera vez, enviaría la consulta con lastID = "", y para las siguientes peticiones establecería lastID al atributo id de la última entidad de la petición anterior. Este enfoque tendrá un rendimiento significativamente mejor que el uso de valores crecientes de skip.

Puedes utilizar el parámetro where en tus consultas para filtrar por diferentes propiedades. Puedes filtrar por múltiples valores dentro del parámetro where.

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

También puedes filtrar entidades por el _change_block(number_gte: Int): esto filtra las entidades que se actualizaron en o después del bloque especificado.

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.

En el siguiente ejemplo, estamos filtrando desafíos con coutcome succeeded y number mayor o igual a 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
}
}
}

En el siguiente ejemplo, estamos filtrando desafíos con coutcome succeeded y number mayor o igual a 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.

El resultado de dicha consulta no cambiará con el tiempo, por ejemplo, consultar en un determinado bloque anterior devolverá el mismo resultado sin importar cuándo se ejecute, con la excepción de que si consultas en un bloque muy cerca de la cabecera de la cadena Ethereum, el resultado podría cambiar si ese bloque resulta no estar en la cadena principal y la cadena se reorganiza. Una vez que un bloque puede considerarse final, el resultado de la consulta no cambiará.

Ten en cuenta que la implementación actual todavía está sujeta a ciertas limitaciones que podrían violar estas garantías. La implementación no siempre puede demostrar que un hash de bloque dado no está en la cadena principal, o que el resultado de una consulta por hash de bloque para un bloque que no puede considerarse final aún podría estar influenciado por una reorganización de bloque que se ejecuta simultáneamente con la consulta. Esto no afecta los resultados de consultas por hash de bloque cuando el bloque es final y se sabe que está en la cadena principal. Este problema explica en detalle cuáles son estas limitaciones.

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

El esquema de tu fuente de datos, es decir, los tipos de entidad, los valores y las relaciones que están disponibles para consultar, se definen a través de [GraphQL Interface Definition Language (IDL)](https://facebook.github.io/graphql/draft/# sec-Type-System).

Los esquemas de GraphQL generalmente definen tipos raíz para queries, subscriptions y mutations. The Graph solo admite queries. El tipo raíz Query para tu subgrafo se genera automáticamente a partir del esquema de GraphQL que se incluye en tu manifiesto de subgrafo.

Nota: nuestra API no expone mutaciones porque se espera que los desarrolladores emitan transacciones directamente contra la cadena de bloques subyacente desde sus aplicaciones.

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