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") {idowner}}
Примечание. При запросе одного объекта поле id
является обязательным и должно быть строкой.
Запрос всех объектов Токен
:
{tokens {idowner}}
При запросе коллекции параметр orderBy
может использоваться для сортировки по определенному атрибуту. Кроме того, orderDirection
можно использовать для указания направления сортировки, asc
по возрастанию или desc
по убыванию.
{tokens(orderBy: price, orderDirection: asc) {idowner}}
Начиная с Graph Node, объекты можно сортировать на основе вложенных содержаний.
В следующем примере мы сортируем токены по имени их владельца:
{tokens(orderBy: owner__name, orderDirection: asc) {idowner {name}}}
В настоящее время Вы можете осуществлять сортировку по одно уровневым типам String
или ID
в полях @entity
и @derivedFrom
. К сожалению, , сортировка по полям, которые являются массивами и вложенными объектами, еще не поддерживается.
При запросе коллекции параметр first
можно использовать для разбиения на страницы с начала коллекции. Стоит отметить, что порядок сортировки по умолчанию осуществляется по идентификатору в восходящем алфавитно-цифровом порядке, а не по времени создания.
Кроме того, параметр skip
можно использовать для пропуска объектов и разбивки на страницы. Например, first:100
показывает первые 100 объектов, а first:100, skip:100
показывает следующие 100 объектов.
В запросах следует избегать использования очень больших значений skip
, так как они обычно плохо работают. Для извлечения большого количества элементов гораздо лучше просматривать объекты на основе атрибута, как показано в последнем примере.
Запрос первых 10 токенов:
{tokens(first: 10) {idowner}}
Чтобы запросить группы объектов в середине коллекции, параметр skip
можно использовать в сочетании с параметром first
, чтобы пропустить указанное количество объектов, начиная с начала коллекции.
Запрос 10 объектов Token
, смещенных на 10 позиций от начала коллекции:
{tokens(first: 10, skip: 10) {idowner}}
Если клиенту необходимо получить большое количество объектов, гораздо более эффективно основывать запросы на атрибуте и фильтровать по этому атрибуту. Например, клиент может получить большое количество токенов с помощью этого запроса:
query manyTokens($lastID: String) {tokens(first: 1000, where: { id_gt: $lastID }) {idowner}}
В первый раз он будет отправлять запрос с lastID = ""
, а для последующих запросов будет устанавливать lastID
в атрибут id
последнего объекта в предыдущем запросе. Этот подход будет работать значительно лучше, чем увеличение значений skip
.
Вы можете использовать параметр where
в своих запросах для фильтрации различных свойств. В параметре where
можно фильтровать несколько значений.
Вызовы запросов с результатом failed
:
{challenges(where: { outcome: "failed" }) {challengeroutcomeapplication {id}}}
Вы можете использовать такие суффиксы, как _gt
, _lte
для сравнения значений:
{applications(where: { deposit_gt: "10000000000" }) {idwhitelisteddeposit}}
Вы также можете фильтровать объекты по _change_block(number_gte: Int)
— этот код фильтрует объекты, которые были обновлены в указанном блоке или после него.
Это может быть полезно, если Вы хотите получить только объекты, которые изменились, например, с момента последнего опроса. Или, в качестве альтернативы, может быть полезно исследовать или отладить изменнения объектов в Вашем субграфе (в сочетании с фильтрацией блоков Вы можете изолировать только объекты, которые изменились в определенном блоке).
{applications(where: { _change_block: { number_gte: 100 } }) {idwhitelisteddeposit}}
Фильтрация по вложенным объектам возможна в полях с суффиксом _
.
Это может быть полезно, если Вы хотите получать только объекты, у которых объекты дочернего уровня удовлетворяют заданным условиям.
{challenges(where: { application_: { id: 1 } }) {challengeroutcomeapplication {id}}}
Начиная с Graph Node , Вы можете группировать несколько параметров в одном и том же аргументе where
с использованием операторов and
или or
для фильтрации результатов на основе более чем одного критерия.
В следующем примере мы отфильтровываем задачи с outcome
succeeded
и number
больше или равным 100
.
{challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {challengeroutcomeapplication {id}}}
Syntactic sugar:. Вы можете упростить приведенный выше запрос, удалив оператор and
, передав подвыражение, разделенное запятыми.
{challenges(where: { number_gte: 100, outcome: "succeeded" }) {challengeroutcomeapplication {id}}}
В следующем примере мы отфильтровываем задачи с outcome
succeeded
или number
больше или равным 100
.
{challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {challengeroutcomeapplication {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)
Вы можете запрашивать состояние своих объектов не только для последнего блока, который используется по умолчанию, но и для произвольного блока в прошлом. Блок, в котором должен выполняться запрос, можно указать либо по номеру блока, либо по его хэшу, включив аргумент block
в поля верхнего уровня запросов.
Результат такого запроса не изменится со временем, т.е. запрос к конкретному прошлому блоку будет возвращать один и тот же результат каждый раз при его выполнении, за исключением того, когда Вы запрашиваете блок, очень близкий к началу цепочки, результат в этом случае может измениться, если этот блок окажется не в основной сети и сеть будет реорганизована. После того как блок можно будет считать окончательным, результат запроса не изменится.
Обратите внимание, что текущая реализация имеет определенные ограничения, которые могут нарушить эти гарантии. На данный момент не всегда можно определить, что заданный хэш блока вообще не находится в основной цепочке или что на результат запроса по хэшу блока для блока, который нельзя считать окончательным, может повлиять реорганизация блока, которая происходит одновременно с запросом. Это не влияет на результаты запросов по хэшу блока, когда известно, что блок в конечном итоге находится в основной цепочке. Здесь подробно описана .
{challenges(block: { number: 8000000 }) {challengeroutcomeapplication {id}}}
Этот запрос вернет объекты Challenge
и связанные с ними объекты Application
в том виде, в каком они существовали сразу после обработки блока номер 8 000 000.
{challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {challengeroutcomeapplication {id}}}
Этот запрос вернет объекты Challenge
и связанные с ними объекты Application
в том виде, в каком они существовали сразу после обработки блока с заданным хешем.
Поля запроса полнотекстового поиска предоставляют API-интерфейс содержательного текстового поиска, который можно добавить в схему субграфа и настроить. См. , чтобы добавить полнотекстовый поиск в свой субграф.
Запросы полнотекстового поиска имеют одно обязательное поле, text
, для предоставления поисковых запросов. В этом поле поиска text
можно использовать несколько специальных операторов полнотекстового поиска.
Полнотекстовые поисковые операторы:
Символ | Оператор | Описание |
---|---|---|
& | And | Для объединения нескольких условий поиска в фильтр для объектов, которые включают все указанные условия |
| | Or | Запросы с несколькими условиями поиска, разделенные оператором or, вернут все объекты, которые соответствуют любому из предоставленных условий |
<-> | Follow by | Укажите расстояние между двумя словами. |
:* | Prefix | Используйте поисковый запрос по префиксу, чтобы найти слова с соответствующим префиксом (необходимо 2 символа) |
Используя оператор or
, этот запрос отфильтрует объекты блога с вариантами «anarchism» или «crumpet» в их полнотекстовых полях.
{blogSearch(text: "anarchism | crumpets") {idtitlebodyauthor}}
Оператор follow by
указывает слова на определенном расстоянии друг от друга в полнотекстовых документах. Следующий запрос вернет все блоги с вариантами «decentralize», за которыми следует «philosophy»
{blogSearch(text: "decentralized <-> philosophy") {idtitlebodyauthor}}
Комбинируйте полнотекстовые операторы, чтобы создавать более сложные фильтры. С оператором поиска по префиксу в сочетании с запросом «follow by» будут найдены все объекты блога со словами, начинающимися с «lou», за которыми следует «music».
{blogSearch(text: "lou:* <-> music") {idtitlebodyauthor}}
Graph Node реализует проверку запросов GraphQL, которые получает с помощью , основанного на . Запросы, которые не соответствуют правилу проверки, вызывают стандартную ошибку. Подробнее см. в .
Схема Вашего источника данных, то есть типы объектов, значения и отношения, доступные для запроса, определяется с помощью .
Схемы GraphQL обычно определяют корневые типы для queries
, subscriptions
и mutations
. The Graph поддерживает только queries
. Корневой тип Query
для вашего субграфа автоматически создается из схемы GraphQL, включенной в манифест вашего субграфа.
Примечание. Наш API не подвергается мутации, поскольку ожидается, что разработчики будут выполнять транзакции непосредственно в базовом блокчейне из своих приложений.
Все типы GraphQL с директивами @entity
в Вашей схеме будут рассматриваться как объекты и должны иметь поле ID
.
Примечание. В настоящее время все типы в Вашей схеме должны иметь директиву @entity
. В будущем мы будем рассматривать типы без директивы @entity
как объекты значений, но это пока не поддерживается.
Все субграфы имеют автоматически сгенерированный объект _Meta_
, который обеспечивает доступ к метаданным субграфа. Запросить это можно следующим образом:
{_meta(block: { number: 123987 }) {block {numberhashtimestamp}deploymenthasIndexingErrors}}
Если предоставлен блок, метаданные относятся к этому блоку, в противном случае используется последний проиндексированный блок. Если предоставляется блок, он должен быть после начального блока субграфа и меньше или равен последнему проиндексированному блоку.
deployment
— это уникальный идентификатор, соответствующий CID IPFS файла subgraph.yaml
.
block
предоставляет информацию о последнем блоке (с учетом всех ограничений блока, переданных в _meta
):
- hash: хэш блока
- number: номер блока
- timestamp: временная метка блока, если она доступна (в настоящее время доступна только для субграфов, индексирующих сети EVM)
hasIndexingErrors
— логическое значение, определяющее, обнаружил ли субграф ошибки индексации в каком-то предыдущем блоке