subgraphs > Querying > API GraphQL

API GraphQL

Reading time: 9 min

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.

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.

Запрос на один объект Token, определенный в Вашей схеме:

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

Запрос всех объектов Токен:

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

Пример сортировки вложенных объектов

Ссылка на этот раздел

Начиная с Graph Node, объекты v0.30.0 можно сортировать на основе вложенных содержаний.

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

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

В настоящее время Вы можете осуществлять сортировку по одно уровневым типам String или ID в полях @entity и @derivedFrom. К сожалению, сортировка по интерфейсам на одно уровневых структурах, сортировка по полям, которые являются массивами и вложенными объектами, еще не поддерживается.

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.

Пример использования first

Ссылка на этот раздел

Запрос первых 10 токенов:

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

Чтобы запросить группы объектов в середине коллекции, параметр skip можно использовать в сочетании с параметром first, чтобы пропустить указанное количество объектов, начиная с начала коллекции.

Пример использования first и skip

Ссылка на этот раздел

Запрос 10 объектов Token, смещенных на 10 позиций от начала коллекции:

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

Пример использования first и 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.

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

Пример использования where

Ссылка на этот раздел

Вызовы запросов с результатом failed:

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

Вы можете использовать такие суффиксы, как _gt, _lte для сравнения значений:

Пример фильтрации диапазона

Ссылка на этот раздел
{
applications(where: { deposit_gt: "10000000000" }) {
id
whitelisted
deposit
}
}

Пример фильтрации блока

Ссылка на этот раздел

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

Это может быть полезно, если Вы хотите получить только объекты, которые изменились, например, с момента последнего опроса. Или, в качестве альтернативы, может быть полезно исследовать или отладить изменнения объектов в Вашем субграфе (в сочетании с фильтрацией блоков Вы можете изолировать только объекты, которые изменились в определенном блоке).

{
applications(where: { _change_block: { number_gte: 100 } }) {
id
whitelisted
deposit
}
}

Пример фильтрации вложенных объектов

Ссылка на этот раздел

Фильтрация по вложенным объектам возможна в полях с суффиксом _.

Это может быть полезно, если Вы хотите получать только объекты, у которых объекты дочернего уровня удовлетворяют заданным условиям.

{
challenges(where: { application_: { id: 1 } }) {
challenger
outcome
application {
id
}
}
}

Логические операторы

Ссылка на этот раздел

Начиная с Graph Node v0.30.0, Вы можете группировать несколько параметров в одном и том же аргументе where с использованием операторов and или or для фильтрации результатов на основе более чем одного критерия.

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:. Вы можете упростить приведенный выше запрос, удалив оператор and, передав подвыражение, разделенное запятыми.

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

Примечание. При построении запросов важно учитывать влияние на производительность использования оператора or. Хотя or могут быть полезными инструментами для расширения результатов поиска, они также могут повлечь значительные затраты. Одна из основных проблем с or заключается в том, что это может привести к замедлению запросов. Это связано с тем, что or требует от базы данных сканирования нескольких индексов, что может занять много времени. Чтобы избежать этих проблем, разработчикам рекомендуется использовать операторы and вместо или всякий раз, когда это возможно. Это обеспечивает более точную фильтрацию и может привести к более быстрым и точным запросам.

Полный список суффиксов параметров:

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

Обратите внимание, что некоторые суффиксы поддерживаются только для определенных типов. Например, Boolean поддерживает только _not, _in и _not_in, а _ доступен только для типов объектов и интерфейсов.

Кроме того, в качестве части аргумента where доступны следующие глобальные фильтры:

_change_block(number_gte: Int)

Запросы на Time-travel

Ссылка на этот раздел

Вы можете запрашивать состояние своих объектов не только для последнего блока, который используется по умолчанию, но и для произвольного блока в прошлом. Блок, в котором должен выполняться запрос, можно указать либо по номеру блока, либо по его хэшу, включив аргумент block в поля верхнего уровня запросов.

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

Этот запрос вернет объекты Challenge и связанные с ними объекты Application в том виде, в каком они существовали сразу после обработки блока номер 8 000 000.

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

Этот запрос вернет объекты Challenge и связанные с ними объекты Application в том виде, в каком они существовали сразу после обработки блока с заданным хешем.

Полнотекстовые поисковые запросы

Ссылка на этот раздел

Поля запроса полнотекстового поиска предоставляют API-интерфейс содержательного текстового поиска, который можно добавить в схему субграфа и настроить. См. Defining Fulltext Search Fields, чтобы добавить полнотекстовый поиск в свой субграф.

Запросы полнотекстового поиска имеют одно обязательное поле, text, для предоставления поисковых запросов. В этом поле поиска text можно использовать несколько специальных операторов полнотекстового поиска.

Полнотекстовые поисковые операторы:

СимволОператорОписание
&AndДля объединения нескольких условий поиска в фильтр для объектов, которые включают все указанные условия
|OrЗапросы с несколькими условиями поиска, разделенные оператором or, вернут все объекты, которые соответствуют любому из предоставленных условий
<->Follow byУкажите расстояние между двумя словами.
:*PrefixИспользуйте поисковый запрос по префиксу, чтобы найти слова с соответствующим префиксом (необходимо 2 символа)

Используя оператор or, этот запрос отфильтрует объекты блога с вариантами «anarchism» или «crumpet» в их полнотекстовых полях.

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

Оператор follow by указывает слова на определенном расстоянии друг от друга в полнотекстовых документах. Следующий запрос вернет все блоги с вариантами «decentralize», за которыми следует «philosophy»

{
blogSearch(text: "decentralized <-> philosophy") {
id
title
body
author
}
}

Комбинируйте полнотекстовые операторы, чтобы создавать более сложные фильтры. С оператором поиска по префиксу в сочетании с запросом «follow by» будут найдены все объекты блога со словами, начинающимися с «lou», за которыми следует «music».

{
blogSearch(text: "lou:* <-> music") {
id
title
body
author
}
}

Graph Node реализует на основе спецификаций проверку запросов GraphQL, которые получает с помощью graphql-tools-rs, основанного на референтная реализация graphql-js. Запросы, которые не соответствуют правилу проверки, вызывают стандартную ошибку. Подробнее см. в спецификации 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.

Все типы GraphQL с директивами @entity в Вашей схеме будут рассматриваться как объекты и должны иметь поле ID.

Примечание. В настоящее время все типы в Вашей схеме должны иметь директиву @entity. В будущем мы будем рассматривать типы без директивы @entity как объекты значений, но это пока не поддерживается.

Метаданные субграфа

Ссылка на этот раздел

Все субграфы имеют автоматически сгенерированный объект _Meta_, который обеспечивает доступ к метаданным субграфа. Запросить это можно следующим образом:

{
_meta(block: { number: 123987 }) {
block {
number
hash
timestamp
}
deployment
hasIndexingErrors
}
}

Если предоставлен блок, метаданные относятся к этому блоку, в противном случае используется последний проиндексированный блок. Если предоставляется блок, он должен быть после начального блока субграфа и меньше или равен последнему проиндексированному блоку.

deployment — это уникальный идентификатор, соответствующий CID IPFS файла subgraph.yaml.

block предоставляет информацию о последнем блоке (с учетом всех ограничений блока, переданных в _meta):

  • hash: хэш блока
  • number: номер блока
  • timestamp: временная метка блока, если она доступна (в настоящее время доступна только для субграфов, индексирующих сети EVM)

hasIndexingErrors — логическое значение, определяющее, обнаружил ли субграф ошибки индексации в каком-то предыдущем блоке

Редактировать страницу

Предыдущий
Распределенные системы
Следующий
Subgraph ID vs Deployment ID
Редактировать страницу