Querying > API GraphQL

API GraphQL

Reading time: 8 min

This guide explains the GraphQL Query API that is used for The Graph Protocol.

Запросы

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

В Вашей схеме субграфа Вы определяете типы, называемые Entities. Для каждого типа Entity поле entity и entities будет создано для типа Query верхнего уровня. Обратите внимание, что query не нужно включать в начало запроса graphql при использовании The Graph.

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

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

Примечание. При запросе одного объекта поле id является обязательным и должно быть строкой.

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

{
tokens {
id
owner
}
}

При запросе коллекции параметр orderBy может использоваться для сортировки по определенному атрибуту. Кроме того, orderDirection можно использовать для указания направления сортировки, asc по возрастанию или desc по убыванию.

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

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

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

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

В следующем примере мы сортируем токены по имени их владельца:

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

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

При запросе коллекции параметр first можно использовать для разбиения на страницы с начала коллекции. Стоит отметить, что порядок сортировки по умолчанию осуществляется по идентификатору в восходящем алфавитно-цифровом порядке, а не по времени создания.

Кроме того, параметр skip можно использовать для пропуска объектов и разбивки на страницы. Например, first:100 показывает первые 100 объектов, а first:100, skip:100 показывает следующие 100 объектов.

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

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

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

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

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

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

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

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

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

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

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

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

Если клиенту необходимо получить большое количество объектов, гораздо более эффективно основывать запросы на атрибуте и фильтровать по этому атрибуту. Например, клиент может получить большое количество токенов с помощью этого запроса:

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

В первый раз он будет отправлять запрос с lastID = "", а для последующих запросов будет устанавливать lastID в атрибут id последнего объекта в предыдущем запросе. Этот подход будет работать значительно лучше, чем увеличение значений skip.

Вы можете использовать параметр where в своих запросах для фильтрации различных свойств. В параметре where можно фильтровать несколько значений.

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

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

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

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

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

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

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

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

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

Вы также можете фильтровать объекты по _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 для фильтрации результатов на основе более чем одного критерия.

В следующем примере мы отфильтровываем задачи с outcome succeeded и number больше или равным 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
}
}
}

В следующем примере мы отфильтровываем задачи с outcome succeeded или number больше или равным 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 в поля верхнего уровня запросов.

Результат такого запроса не изменится со временем, т.е. запрос к конкретному прошлому блоку будет возвращать один и тот же результат каждый раз при его выполнении, за исключением того, когда Вы запрашиваете блок, очень близкий к началу цепочки, результат в этом случае может измениться, если этот блок окажется не в основной сети и сеть будет реорганизована. После того как блок можно будет считать окончательным, результат запроса не изменится.

Обратите внимание, что текущая реализация имеет определенные ограничения, которые могут нарушить эти гарантии. На данный момент не всегда можно определить, что заданный хэш блока вообще не находится в основной цепочке или что на результат запроса по хэшу блока для блока, который нельзя считать окончательным, может повлиять реорганизация блока, которая происходит одновременно с запросом. Это не влияет на результаты запросов по хэшу блока, когда известно, что блок в конечном итоге находится в основной цепочке. Здесь подробно описана эта проблема.

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

Схема Вашего источника данных, то есть типы объектов, значения и отношения, доступные для запроса, определяется с помощью GraphQL Interface Definition Langauge (IDL).

Схемы GraphQL обычно определяют корневые типы для queries, subscriptions и mutations. The Graph поддерживает только queries. Корневой тип Query для вашего субграфа автоматически создается из схемы GraphQL, включенной в манифест вашего субграфа.

Примечание. Наш API не подвергается мутации, поскольку ожидается, что разработчики будут выполнять транзакции непосредственно в базовом блокчейне из своих приложений.

Все типы 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
Редактировать страницу