Я работаю разработчиком в компании АО «Центр Электронных Финансов».
Один и наших проектов — портал Государственных закупок Республики Казахстан — goszakup.gov.kz.
Год назад мы запустили большой проект — Унифицированные сервисы (OpenData).
Для реализации была использована методология RestAPI.
Сегодня я расскажу о новой версии наших сервисов и новом интерфейсе работы с ними.
Мы разработали и запустили 6 сервисов Открытых данных:
Многие компании Казахстана уже подключаются и получают данных по данным сервисам.
Запуск Открытых данных позволил примерно на 40% снизить нагрузку базы данных за счет того, что компаниям не нужно писать различные парсера чтобы собирать данных о Государственных закупках. Достаточно пройти не сложный Квест :)
RestAPI дает возможность удобнее и быстрее получить данные чем парсинг сайта, но стандартный RestAPI не дает компаниям гибкости и для построения связи с объектами приходится получать сначала все данные и только потом строить связи между ними.
Для того чтобы получить данные по объявлению необходимо по RestAPI запросить сначала реестр объявлений, затем реестр лотов и в завершении реестр планов. Значит на получение одного объявления необходимо выполнить минимум 3 запроса, а если надо получить данных по 50 объявлениям потребуется минимум 101 запрос к RestAPI при условии, что в каждом объявлении будет по 1 лоту (1 на получение 50 объявлений, 50 на получение лотов, 50 на получение пунктов плана).
Мы нашли способ сократить это количество до Одного запроса!
Мы запускаем 2-ю версию Унифицированных сервисов — ows.goszakup.gov.kz/v2.
Помимо расширения наборов данных мы расширяем и возможность работы с нашим API.
Теперь данные можно получить и по RestAPI и по новому интерфейсу — GraphQL.
ows.goszakup.gov.kz/v2/graphql
Описывать, что такое GraphQL я не буду, для этого вы можете ознакомиться со статьей aliksend — Что же такое этот GraphQL?.
Я расскажу какие преимущества мы получили после запуска GraphQL:
При простом запросе RestAPI вы получаете тот формат данных которые были заложены заранее.
При запросе к GraphQL вы получаете данные в том формате в котором нужно вам.
При запросе данных вы сами определяете формат данных которые нужны, например нужны ИД и
Номер договора
В ответ получаем только эти данные:
Ну такие запросы это самое легкое в реализации GraphQL. Компании получают возможность самим выбирать какие данные они хотят получить, при этом нам не надо вносить каких либо корректировок как если бы это было при работе с RestAPI. Вы получаете только тот набор полей который необходим.
Мы не остановились на том, чтобы повторить функционал RestAPI просто дав возможность частично выбирать данные.
Мы реализовали 2-ю особенность GraphQL — связи объектов.
Если получать данные по RestAPI чтобы получать данные по договору и по компании заказчику в договоре требовалось сначала получить данные из Реестра участников, а только потом получать данные из Реестра договоров и самим строить связь между объектами.
Теперь при работе с GraphQL не нужно выполнять полное получение данных по Реестру участников, достаточно запросить данные в интересующем вас формате:
Тем самым одним запросом мы получаем и данные по договору, и данные по компании заказчику:
И таких связей реализовали много, теперь компаниям для получения данных потребуется значительно меньше запросов для получения данных. При этом больше не надо догадываться как именно связаны друг с другом объекты, получать полные наборы данных чтобы связать их друг с другом.
Я попытался наглядно показать частично структуру связей которой получилось добиться.
Многие сторонники SOAP запросов всегда ставили самым главным плюсом — типизацию данных.
RestAPI в отличие от SOAP не имеет описания своей структуры и вы заранее не знаете какой тип данных. Но GraphQL меняет все.
Теперь можно запросить у GraphQL данные по всей схеме данных и вы получите:
Я для работы с GraphQL использую программу Insomnia REST Client — insomnia.rest
Она при работе с GraphQL получает всю структуру объектов и подсказывает при построении запроса.
Приведу в качестве примера несколько скриншотов.
1. Помощь в построении запросов т.к. программа получила полную структуру объектов
2. Подсказку по описания каждого поля с его типом данных и описанием
3. Подсказку если какое-то поле получило флаг — Deprecated
И данная особенность GraphQL позволяет вам иметь полную картину с какими полями и объектами вы работаете.
И самое интересное я оставил напоследок.
Все вроде бы классно, есть возможность строить свою структуру данных, есть связь с другими объектами, все данных типизированы. Но все же чего-то не хватает…
Не хватает возможности искать по этим данным.
Дна начало был реализован формат поиска с указанием параметров в самом запросе:
Но тут я столкнулся с рядом проблем:
Чтобы упростить построение запросов, и расширить возможность поиска я реализовал вложенные объекты для фильтрации данных.
Определяем в запросе переменную с указанием объекта фильтрации.
Описываем сами параметры поиска данных:
И в результате мы получим все объявления которые имеют статусы 1 и 2.
В самом запросе указываем только структуру данных, а все параметры поиска уходят в передачу параметров где уже можем передавать и массивы данных для фильтрации по нескольким критериям.
При этом в самой схеме GraphQL мы все также имеем описание и такого объекта поиска:
Работают сервисы:
Мы запустили новый функционал, который во много раз упрощает работу с нашим API, имеет гибкую структуру запросов и возможность поиска данных по заданным критериям.
Мы не потеряли в скорости получения данных, а только сокращаем за счет этого количество запросов необходимых для получения данных.
Мы получили возможность предупреждать в схеме данных об отключенных или переименованных полях.
Мы планируем и далее развивать API и дать возможность также морфологического поиска данных по сервисам.
Один и наших проектов — портал Государственных закупок Республики Казахстан — goszakup.gov.kz.
Год назад мы запустили большой проект — Унифицированные сервисы (OpenData).
Для реализации была использована методология RestAPI.
Сегодня я расскажу о новой версии наших сервисов и новом интерфейсе работы с ними.
Мы разработали и запустили 6 сервисов Открытых данных:
- Реестр участников
- Реестр недобросовестных поставщиков
- Реестр годовых планов
- Объявления о гос. закупках
- Реестр лотов
- Реестр договоров
Многие компании Казахстана уже подключаются и получают данных по данным сервисам.
Запуск Открытых данных позволил примерно на 40% снизить нагрузку базы данных за счет того, что компаниям не нужно писать различные парсера чтобы собирать данных о Государственных закупках. Достаточно пройти не сложный Квест :)
- написать запрос на получение токена доступа
- ознакомиться с документацией по сервисам на нашем портале goszakup.gov.kz/ru/developer/ows
- написать свой RestAPI клиент
Унифицированные сервисы — Новый подход
RestAPI дает возможность удобнее и быстрее получить данные чем парсинг сайта, но стандартный RestAPI не дает компаниям гибкости и для построения связи с объектами приходится получать сначала все данные и только потом строить связи между ними.
Для того чтобы получить данные по объявлению необходимо по RestAPI запросить сначала реестр объявлений, затем реестр лотов и в завершении реестр планов. Значит на получение одного объявления необходимо выполнить минимум 3 запроса, а если надо получить данных по 50 объявлениям потребуется минимум 101 запрос к RestAPI при условии, что в каждом объявлении будет по 1 лоту (1 на получение 50 объявлений, 50 на получение лотов, 50 на получение пунктов плана).
Мы нашли способ сократить это количество до Одного запроса!
Мы запускаем 2-ю версию Унифицированных сервисов — ows.goszakup.gov.kz/v2.
Помимо расширения наборов данных мы расширяем и возможность работы с нашим API.
Теперь данные можно получить и по RestAPI и по новому интерфейсу — GraphQL.
ows.goszakup.gov.kz/v2/graphql
Описывать, что такое GraphQL я не буду, для этого вы можете ознакомиться со статьей aliksend — Что же такое этот GraphQL?.
Я расскажу какие преимущества мы получили после запуска GraphQL:
- Гибкость запросов;
- Получение связанных объектов;
- Полную типизацию запросов и ответов;
- Новый интерфейс поиска данных.
Гибкость запросов
При простом запросе RestAPI вы получаете тот формат данных которые были заложены заранее.
При запросе к GraphQL вы получаете данные в том формате в котором нужно вам.
При запросе данных вы сами определяете формат данных которые нужны, например нужны ИД и
Номер договора
{
contract
{
id
contract_number_sys
}
}
В ответ получаем только эти данные:
{
"data": {
"contract": [
{
"id": 1,
"contract_number_sys": "номер_договора"
}
]
}
}
Ну такие запросы это самое легкое в реализации GraphQL. Компании получают возможность самим выбирать какие данные они хотят получить, при этом нам не надо вносить каких либо корректировок как если бы это было при работе с RestAPI. Вы получаете только тот набор полей который необходим.
Получение связанных объектов
Мы не остановились на том, чтобы повторить функционал RestAPI просто дав возможность частично выбирать данные.
Мы реализовали 2-ю особенность GraphQL — связи объектов.
Если получать данные по RestAPI чтобы получать данные по договору и по компании заказчику в договоре требовалось сначала получить данные из Реестра участников, а только потом получать данные из Реестра договоров и самим строить связь между объектами.
Теперь при работе с GraphQL не нужно выполнять полное получение данных по Реестру участников, достаточно запросить данные в интересующем вас формате:
{
contract
{
id
contract_number_sys
customer
{
name_ru
}
}
}
Тем самым одним запросом мы получаем и данные по договору, и данные по компании заказчику:
{
"data": {
"contract": [
{
"id": 1,
"contract_number_sys": "номер_договора",
"customer" : {
"name_ru": "Компания Мира"
}
}
]
}
}
И таких связей реализовали много, теперь компаниям для получения данных потребуется значительно меньше запросов для получения данных. При этом больше не надо догадываться как именно связаны друг с другом объекты, получать полные наборы данных чтобы связать их друг с другом.
Я попытался наглядно показать частично структуру связей которой получилось добиться.
Типизация запросов и ответов
Многие сторонники SOAP запросов всегда ставили самым главным плюсом — типизацию данных.
RestAPI в отличие от SOAP не имеет описания своей структуры и вы заранее не знаете какой тип данных. Но GraphQL меняет все.
Теперь можно запросить у GraphQL данные по всей схеме данных и вы получите:
- Полное описание структуры данных;
- Описание какое поле какой имеет тип данных (Int, String, Boolean);
- Описание вложенных объектов и структуры полей вложенных объектов;
- Детальное описание например на русском языке для каждого поля;
- Получения уведомления, что какое-то поле получило флаг Deprecated с описанием.
Я для работы с GraphQL использую программу Insomnia REST Client — insomnia.rest
Она при работе с GraphQL получает всю структуру объектов и подсказывает при построении запроса.
Приведу в качестве примера несколько скриншотов.
1. Помощь в построении запросов т.к. программа получила полную структуру объектов
2. Подсказку по описания каждого поля с его типом данных и описанием
3. Подсказку если какое-то поле получило флаг — Deprecated
И данная особенность GraphQL позволяет вам иметь полную картину с какими полями и объектами вы работаете.
Новый интерфейс поиска данных
И самое интересное я оставил напоследок.
Все вроде бы классно, есть возможность строить свою структуру данных, есть связь с другими объектами, все данных типизированы. Но все же чего-то не хватает…
Не хватает возможности искать по этим данным.
Дна начало был реализован формат поиска с указанием параметров в самом запросе:
{
trd_buy(ref_buy_status_id: 1)
{
name_kz
name_ru
}
}
Но тут я столкнулся с рядом проблем:
- при большом количестве критериев поиска запрос становится просто не читаемым;
- невозможно определить массив при поиске данных для поиска по нескольким вариантам одного поля.
Чтобы упростить построение запросов, и расширить возможность поиска я реализовал вложенные объекты для фильтрации данных.
Определяем в запросе переменную с указанием объекта фильтрации.
query($filter: TrdBuyFiltersInput){
trd_buy(filters: $filter)
{
name_kz
name_ru
}
}
Описываем сами параметры поиска данных:
{
"filter": {
"ref_buy_status_id": [1, 2]
}
}
И в результате мы получим все объявления которые имеют статусы 1 и 2.
В самом запросе указываем только структуру данных, а все параметры поиска уходят в передачу параметров где уже можем передавать и массивы данных для фильтрации по нескольким критериям.
При этом в самой схеме GraphQL мы все также имеем описание и такого объекта поиска:
Унифицированные сервисы — Версия 2.0:
Работают сервисы:
- Реестр участников
- Реестр объявлений
- Реестр договоров
- Реестр актов
- Реестр лотов
- Реестр годовых планов
- Реестр недобросовестных поставщиков
Мы запустили новый функционал, который во много раз упрощает работу с нашим API, имеет гибкую структуру запросов и возможность поиска данных по заданным критериям.
Мы не потеряли в скорости получения данных, а только сокращаем за счет этого количество запросов необходимых для получения данных.
Мы получили возможность предупреждать в схеме данных об отключенных или переименованных полях.
Мы планируем и далее развивать API и дать возможность также морфологического поиска данных по сервисам.
lovecode
Приятно узнать что сервис такого уровня в Родном Казахстане начал публиковать GraphQL API.
Расскажите:
GHostly_FOX Автор
1. PHP с библиотекой graphql-php
2. На текущий момент нет проблем с «излишней гибкостью», в качестве хранения данных используется NoSQL хранилище. А проблема с так называемыми N+1 решена за счет использования буферов.
Если хотите получить 50 объявлений с лотами и планами то к хранилищу будет отправлено всего 3 запроса.