8 минуты
API GraphQL
Узнайте о GraphQL API запросах, используемых в The Graph.
Что такое 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.
Запросы с GraphQL
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.
Примечание: query
не нужно указывать в начале graphql
запроса при использовании The Graph.
Примеры
Запрос для одного объекта Token
, определенного в Вашей схеме:
1{2 token(id: "1") {3 id4 owner5 }6}
Примечание: При запросе одного объекта поле id
является обязательным и должно быть записано как строка.
Запрос всех объектов Token
:
1{2 tokens {3 id4 owner5 }6}
Сортировка
При запросе коллекции Вы можете:
- Использовать параметр
orderBy
для сортировки по определенному атрибуту. - Использовать параметр
orderDirection
, чтобы указать направление сортировкиasc
для возрастания илиdesc
для убывания.
Пример
1{2 tokens(orderBy: price, orderDirection: asc) {3 id4 owner5 }6}
Пример сортировки вложенных объектов
Начиная с Graph Node v0.30.0
, объекты можно сортировать на основе вложенных объектов.
В следующем примере мы сортируем токены по имени их владельца:
1{2 tokens(orderBy: owner__name, orderDirection: asc) {3 id4 owner {5 name6 }7 }8}
В настоящее время сортировка возможна по одноуровневым полям типа String
или ID
, в полях @entity
и @derivedFrom
. К сожалению, сортировка по интерфейсам в одноуровневых объектах, сортировка по полям-массивам и вложенным объектам пока не поддерживается.
Пагинация
При запросе коллекции лучше всего:
- Использовать параметр
first
для пагинации данных с начала коллекции.- Стандартная сортировка выполняется по
ID
в возрастающем алфавитно-числовом порядке, не по времени создания.
- Стандартная сортировка выполняется по
- Использовать параметр
skip
, чтобы пропускать объекты и осуществлять пагинацию. Например,first:100
покажет первые 100 объектов, аfirst:100, skip:100
покажет следующие 100 объектов. - Избегайте использования
skip
в запросах, так как это обычно приводит к низкой производительности. Для получения большого количества элементов лучше выполнять постраничную загрузку объектов на основе атрибута, как показано в предыдущем примере.
Пример использования first
Запрос первых 10 токенов:
1{2 tokens(first: 10) {3 id4 owner5 }6}
Чтобы запросить группы объектов в середине коллекции, параметр skip
можно использовать в сочетании с параметром first
, чтобы пропустить указанное количество объектов, начиная с начала коллекции.
Пример использования first
и skip
Запрос 10 объектов Token
, смещенных на 10 позиций от начала коллекции:
1{2 tokens(first: 10, skip: 10) {3 id4 owner5 }6}
Пример использования first
и id_ge
Если клиенту нужно получить большое количество объектов, эффективнее выполнять запросы на основе атрибута и фильтровать по этому атрибуту. Например, клиент может получить большое количество токенов с помощью следующего запроса:
1query manyTokens($lastID: String) {2 tokens(first: 1000, where: { id_gt: $lastID }) {3 id4 owner5 }6}
В первый раз запрос отправляется с lastID = ""
, а в последующих запросах lastID
устанавливается в значение атрибута id
последнего объекта из предыдущего запроса. Этот подход значительно эффективнее, чем использование увеличивающихся значений skip
.
Фильтрация
- Вы можете использовать параметр
where
в запросах для фильтрации по различным свойствам. - Вы можете фильтровать по нескольким значениям внутри параметра
where
.
Пример использования where
Запрос задач с результатом failed
:
1{2 challenges(where: { outcome: "failed" }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Вы можете использовать такие суффиксы, как _gt
, _lte
для сравнения значений:
Пример фильтрации диапазона
1{2 applications(where: { deposit_gt: "10000000000" }) {3 id4 whitelisted5 deposit6 }7}
Пример фильтрации блока
Вы также можете фильтровать объекты, которые были обновлены на указанном блоке или позже, с помощью _change_block(number_gte: Int)
.
This can be useful if you are looking to fetch only entities which have changed, for example since the last time you polled. Or alternatively it can be useful to investigate or debug how entities are changing in your Subgraph (if combined with a block filter, you can isolate only entities that changed in a specific block).
1{2 applications(where: { _change_block: { number_gte: 100 } }) {3 id4 whitelisted5 deposit6 }7}
Пример фильтрации вложенных объектов
Фильтрация на основе вложенных объектов возможна в полях с суффиксом _
.
Это может быть полезно, если Вы хотите получать только объекты, у которых объекты дочернего уровня удовлетворяют заданным условиям.
1{2 challenges(where: { application_: { id: 1 } }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Логические операторы
Начиная с Graph Node v0.30.0
, Вы можете группировать несколько параметров в одном аргументе where
, используя операторы and
или or
для фильтрации результатов по нескольким критериям.
Оператор AND
Следующий пример фильтрует задачи с outcome
succeeded
и number
больше или равно 100
.
1{2 challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Синтаксический сахар: Вы можете упростить приведенный выше запрос, убрав оператор and
и передав подвыражение, разделенное запятыми.
1{2 challenges(where: { number_gte: 100, outcome: "succeeded" }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Оператор OR
Следующий пример фильтрует задачи с outcome
succeeded
или number
больше или равно 100
.
1{2 challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Примечание: При составлении запросов важно учитывать влияние оператора or
на производительность. Хотя or
может быть полезным инструментом для расширения результатов поиска, он также может значительно замедлить запросы. Основная проблема в том, что or
заставляет базу данных сканировать несколько индексов, что может быть ресурсоемким процессом. Чтобы избежать этих проблем, рекомендуется по возможности использовать оператор and
вместо or
. Это позволяет выполнять более точную фильтрацию и делает запросы быстрее и эффективнее.
Все фильтры
Полный список суффиксов параметров:
1_2_not3_gt4_lt5_gte6_lte7_in8_not_in9_contains10_contains_nocase11_not_contains12_not_contains_nocase13_starts_with14_starts_with_nocase15_ends_with16_ends_with_nocase17_not_starts_with18_not_starts_with_nocase19_not_ends_with20_not_ends_with_nocase
Обратите внимание, что некоторые суффиксы поддерживаются только для определенных типов. Например, Boolean
поддерживает только _not
, _in
и _not_in
, тогда как _
доступен только для объектных и интерфейсных типов.
Кроме того, в качестве части аргумента where
доступны следующие глобальные фильтры:
1_change_block(number_gte: Int)
Запросы на Time-travel
Вы можете запрашивать состояние своих объектов не только для последнего блока, который используется по умолчанию, но и для произвольного блока в прошлом. Блок, в котором должен выполняться запрос, можно указать либо по номеру блока, либо по его хэшу, включив аргумент block
в поля верхнего уровня запросов.
Результат такого запроса не изменится со временем, то есть запрос на определенном прошедшем блоке вернет тот же результат, независимо от времени выполнения, за исключением случая, когда запрос выполняется на блоке, который находится очень близко к началу чейна. В этом случае результат может измениться, если этот блок окажется не на основном чейне, и чейн будет реорганизован. Как только блок можно будет считать окончательным, результат запроса больше не изменится.
Примечание: Текущая реализация все еще подвержена определенным ограничениям, которые могут нарушить эти гарантии. Реализация не всегда может точно определить, что данный хэш блока вообще не находится на основном чейне, или что результат запроса по хэшу блока для блока, который еще не считается окончательным, может быть изменен из-за реорганизации блоков, происходящей одновременно с запросом. Эти ограничения не влияют на результаты запросов по хэшу блока, если блок окончателен и подтвержден на основном чейне. Этот вопрос подробно объясняет, в чем состоят эти ограничения.
Пример
1{2 challenges(block: { number: 8000000 }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Этот запрос вернет объекты Challenge
и связанные с ними объекты Application
в том виде, в каком они существовали сразу после обработки блока номер 8,000,000.
Пример
1{2 challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {3 challenger4 outcome5 application {6 id7 }8 }9}
Этот запрос вернет объекты Challenge
и связанные с ними объекты Application
в том виде, в каком они существовали сразу после обработки блока с заданным хешем.
Полнотекстовые поисковые запросы
Fulltext search query fields provide an expressive text search API that can be added to the Subgraph schema and customized. Refer to Defining Fulltext Search Fields to add fulltext search to your Subgraph.
Запросы полнотекстового поиска имеют одно обязательное поле, text
, для предоставления поисковых запросов. В этом поле поиска text
можно использовать несколько специальных операторов полнотекстового поиска.
Полнотекстовые поисковые операторы:
Символ | Оператор | Описание |
---|---|---|
& | And | Для объединения нескольких условий поиска в фильтр для объектов, которые включают все указанные условия |
| | Or | Запросы с несколькими условиями поиска, разделенные оператором or, вернут все объекты, которые соответствуют любому из предоставленных условий |
<-> | Follow by | Укажите расстояние между двумя словами. |
:* | Prefix | Используйте поисковый запрос по префиксу, чтобы найти слова с соответствующим префиксом (необходимо 2 символа) |
Примеры
Используя оператор or
, этот запрос отфильтрует объекты блога, содержащие варианты слов “anarchism” или “crumpet” в их полнотекстовых полях.
1{2 blogSearch(text: "anarchism | crumpets") {3 id4 title5 body6 author7 }8}
Оператор follow by
определяет слова, находящиеся на определённом расстоянии друг от друга в полнотекстовых документах. Следующий запрос вернёт все блоги, содержащие варианты слова “decentralize”, за которым следует “philosophy”
1{2 blogSearch(text: "decentralized <-> philosophy") {3 id4 title5 body6 author7 }8}
Комбинируйте полнотекстовые операторы, чтобы создавать более сложные фильтры. С оператором поиска по префиксу в сочетании с запросом «follow by» будут найдены все объекты блога со словами, начинающимися с «lou», за которыми следует «music».
1{2 blogSearch(text: "lou:* <-> music") {3 id4 title5 body6 author7 }8}
Валидация
Graph Node реализует валидацию на основе спецификации для получаемых GraphQL-запросов с использованием graphql-tools-rs, которая основана на референсной реализации graphql-js. Запросы, не прошедшие проверку валидации, завершаются стандартной ошибкой. Ознакомьтесь со спецификацией GraphQL, чтобы узнать больше.
Схема
Схема Ваших источников данных, то есть типы объектов, значения и связи, доступные для запросов, определяется с помощью Языка определения интерфейсов GraphQL (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.
Примечание: Наш API не подвергается мутациям, поскольку ожидается, что разработчики будут отправлять транзакции напрямую на базовый блокчейн из своих приложений.
Объекты
Все типы GraphQL с директивами @entity
в Вашей схеме будут рассматриваться как объекты и должны содержать поле ID
.
Примечание: В настоящее время все типы в Вашей схеме должны иметь директиву @entity
. В будущем мы будем рассматривать типы без директивы @entity
как объекты значений, но на данный момент это не поддерживается.
Метаданные субграфа
All Subgraphs have an auto-generated _Meta_
object, which provides access to Subgraph metadata. This can be queried as follows:
1{2 _meta(block: { number: 123987 }) {3 block {4 number5 hash6 timestamp7 }8 deployment9 hasIndexingErrors10 }11}
If a block is provided, the metadata is as of that block, if not the latest indexed block is used. If provided, the block must be after the Subgraph’s start block, and less than or equal to the most recently indexed block.
deployment
— это уникальный идентификатор, соответствующий IPFS CID файла subgraph.yaml
.
block
предоставляет информацию о последнем блоке (с учетом любых ограничений блоков, переданных в _meta
):
- hash: хэш блока
- number: номер блока
- timestamp: the timestamp of the block, if available (this is currently only available for Subgraphs indexing EVM networks)
hasIndexingErrors
is a boolean identifying whether the Subgraph encountered indexing errors at some past block