API GraphQL
Reading time: 10 min
This guide explains the GraphQL Query API that is used for The Graph Protocol.
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") {idowner}}
Nota: Cuando se consulta una sola entidad, el campo id
es obligatorio y debe ser un string.
Consulta todas las entidades Token
:
{tokens {idowner}}
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) {idowner}}
A partir de Graph Node , 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) {idowner {name}}}
Actualmente, puedes ordenar por tipos String
o ID
de un solo nivel en campos @entity
y @derivedFrom
. Desafortunadamente, , 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.
Consulta los primeros 10 tokens:
{tokens(first: 10) {idowner}}
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.
Consulta 10 entidades Token
, desplazadas 10 lugares desde el principio de la colección:
{tokens(first: 10, skip: 10) {idowner}}
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 }) {idowner}}
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
.
Desafíos de consulta con resultado failed
:
{challenges(where: { outcome: "failed" }) {challengeroutcomeapplication {id}}}
Puedes utilizar sufijos como _gt
, _lte
para la comparación de valores:
{applications(where: { deposit_gt: "10000000000" }) {idwhitelisteddeposit}}
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 } }) {idwhitelisteddeposit}}
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 } }) {challengeroutcomeapplication {id}}}
A partir de Graph Node 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" }] }) {challengeroutcomeapplication {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" }) {challengeroutcomeapplication {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" }] }) {challengeroutcomeapplication {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.
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)
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. explica en detalle cuáles son estas limitaciones.
{challenges(block: { number: 8000000 }) {challengeroutcomeapplication {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" }) {challengeroutcomeapplication {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.
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 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í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 |
| | O | 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. |
:* | Prefijo | Utilice 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") {idtitlebodyauthor}}
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") {idtitlebodyauthor}}
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") {idtitlebodyauthor}}
Graph Node implementa una validación 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]( /tree/main/src/validation). Las consultas que fallan en una regla de validación lo hacen con un error estándar: visita las 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)]( 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.
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 {numberhashtimestamp}deploymenthasIndexingErrors}}
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