Хабрахабр

Унифицированные сервисы goszakup.gov.kz — Версия 2

Я работаю разработчиком в компании АО «Центр Электронных Финансов».
Один и наших проектов — портал Государственных закупок Республики Казахстан — goszakup.gov.kz.

Год назад мы запустили большой проект — Унифицированные сервисы (OpenData).
Для реализации была использована методология RestAPI.

Сегодня я расскажу о новой версии наших сервисов и новом интерфейсе работы с ними.


Мы разработали и запустили 6 сервисов Открытых данных:

  • Реестр участников
  • Реестр недобросовестных поставщиков
  • Реестр годовых планов
  • Объявления о гос. закупках
  • Реестр лотов
  • Реестр договоров

Многие компании Казахстана уже подключаются и получают данных по данным сервисам.
Запуск Открытых данных позволил примерно на 40% снизить нагрузку базы данных за счет того, что компаниям не нужно писать различные парсера чтобы собирать данных о Государственных закупках. Достаточно пройти не сложный Квест 🙂

  1. написать запрос на получение токена доступа
  2. ознакомиться с документацией по сервисам на нашем портале goszakup.gov.kz/ru/developer/ows
  3. написать свой RestAPI клиент

Унифицированные сервисы — Новый подход

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

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

Мы запускаем 2-ю версию Унифицированных сервисов — ows.goszakup.gov.kz/v2.
По мимо расширения наборов данных мы расширяем и возможность работы с нашим API.

Теперь данные можно получить и по RestAPI и по новому интерфейсу — GraphQL.
ows.goszakup.gov.kz/v2/graphql

Описывать, что такое GraphQL я не буду, для этого вы можете ознакомиться со статьей aliksend — Что же такое этот GraphQL?.

Я расскажу с какие преимущества мы получили после запуска GraphQL:

  • гибкость запросов;
  • получение связанных объектов;
  • полную типизацию запросов и ответов;
  • новый интерфейс поиска данных.

Гибкость запросов

При простом запросе RestAPI вы получаете тот формат данных которые были заложены заранее.
При запросе к GraphQL вы получаете данные в том формате в котором нужно вам.

При запросе данных вы сами определяете формат данных которые нужны, например нужны ИД и

Номер договора


}

В ответ получаем только эти данные:

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

Подсказку если какое-то поле получило флаг — Deprecated 3.

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

Новый интерфейс поиска данных

И самое интересное я оставил на последок.

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

Не хватает возможности искать по этим данным.

Дна начало был реализован формат поиска с указанием параметров в самом запросе:

{ trd_buy(ref_buy_status_id: 1) { name_kz name_ru }
}

Но тут я столкнулся с рядом проблем:

  1. при большом количестве критериев поиска запрос становится просто не читаемым;
  2. невозможно определить массив при поиске данных для поиска по нескольким вариантам одного поля.

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

Определяем в запросе переменную с указанием объекта фильтрации.

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 и дать возможность так-же морфологического поиска данных по сервисам.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть