Повернення інформації про загальну кількість записів при пагінації критеріїв пошуку

🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію.

1. Загальний опис

Наявна функціональність пагінації не надає можливості через API отримати загальну кількість елементів по критерію пошуку, по якому був виконаний запит. Зовнішнім системам доводиться перебирати всі сторінки ресурсу до пустої відповіді. Це незручно в розробці, та ускладнює можливість надати зручний інтерфейс кінцевому користувачу.

Для поліпшення досвіду користувача пропонується реалізувати можливість створення критеріїв пошуку з новим типом пагінації, які будуть додатково повертати інформацію про поточну сторінку, кількість елементів на сторінці, загальну кількість елементів та загальну кількість сторінок.

2. Актори та ролі користувачів

  • Розробник регламенту

  • Зовнішні системи

3. Загальні принципи та положення

  • Поведінка і контракт існуючих критеріїв пошуку не змінюється.

  • Зберігається зворотня сумісність конфігурації критеріїв пошуку.

4. Функціональні сценарії

  • Налаштування критеріїв пошуку

  • Генерація сервісів критеріїв пошуку

  • Синхронний виклик API критерію пошуку

  • Асинхронний виклик API критерію пошуку

  • Виклик API критерію пошуку із зовнішніх систем, з "Трембіта" і без

5. Поточна реалізація

Поточна реалізація надає можливість передавати offset та limit при визові API критерію пошуку. Ця можливість включена за замовчанням для всіх критеріїв пошуку, ала може бути вимкнута за допомогою атрибута тега createSearchCondition pagination=false.

Відповідь API, незалежно від того включена опція пагінації чи ні, містить тільки масив елементів по яким був здійснений пошук. Інформація про загальну кількість елементів чи сторінок у відповіді не передбачена. При цьому якщо були передані offset та limit то відповідь формується з їх урахуванням.

6. Цільовий дизайн

6.1. Схема та модуль розширення тегів Liquibase

В схемі розширених тегів тип атрибуту pagination змінюється на enum, який складається з наступних значень offset, none, page та true і false які є синонімами offset та none для зворотньої сумісності.

Схема розширених тегів Liquibase
	<xsd:simpleType name="paginationType">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="offset"/>
			<xsd:enumeration value="page"/>
			<xsd:enumeration value="none"/>
      <!--Following is for the backward compatibility-->
			<xsd:enumeration value="true"/> <!--Synonym for "offset"-->
			<xsd:enumeration value="false"/> <!--Synonym for "none"-->
		</xsd:restriction>
	</xsd:simpleType>
  ....
	<xsd:complexType name="selectSearchConditionType">
		....
		<xsd:attribute name="pagination" type="paginationType" use="optional" default="offset"/>
	</xsd:complexType>

В модуль розширення тегів Liquibase додається можливість запису значення атрибуту pagination для нових типів пагінації в таблицю метаданих ddm_liquibase_metadata, при обробці тегу createSearchCondition.

6.2. Сервіс генератор

Значення offset і none є заміною для true і false. Якщо на критерій пошуку атрибут pagination встановлено в offset чи none, логіка генерації сервісів має бути такою як вона я є для true і false відповідно.

Якщо на критерій пошуку атрибут pagination встановлено в page, має бути згенерований сервіс який додатково до фільтрів заданих в критерії пошуку приймає:

pageSize

бажана кількість елементів на сторінці. За замовчанням 10

pageNo

бажаний номер сторінки. За замовчанням 0

У відповіді мають міститися наступні атрибути

content

масив елементів по яким відбувся пошук, обмежений номером сторінки та кількістю елементів на сторінці

totalElements

загальна кількість елементів по запиту

totalPages

загальна кількість сторінок по запиту

pageSize

кількість елементів на сторінці

pageNo

номер сторінки що повертається

Наприклад
{
  "content": [
    {
      "col1": "ADMIN"
    },
    {
      "col1": "USER"
    }
  ],
  "totalElements": 1,
  "totalPages": 1,
  "pageNo": 0,
  "pageSize": 20,
}

Для отримання content сервіс виконує запит до БД, який генерується таким же чином як і в поточній реалізації обробки запиту з limit та offset. При цьому значення limit та offset беруться не напряму з запиту API, а вираховуються з отриманих pageSize і pageNo. Де limit=pageSize, а offset=pageSize*pageNo

Для отримання totalElements сервіс виконує додатковий запит до БД, який генерується за наступним шаблоном

SELECT COUNT(*)
  FROM <search_condition_view>
 WHERE <filtering conditions>

totalPages дорівнює ceil(totalElements/pageSize)

pageNo та pageSize ті які були застосовані у запиті - за вхідними параметрами чи за замовчанням.

Приклад OpenAPI специфікації (Завантажити)

Також має бути згенерований еквівалентний Kafka API для асинхронної взаємодії і SOAP для взаємодії з зовнішніми системами, якщо відповідні опції включені в регламенті реєстру для критерію пошуку.

Spring має стандартні засоби для реалізації пагінації цього типу. Приклад імплементації Using jOOQ With Spring: Sorting and Pagination

6.3. Компоненти системи та їх призначення в рамках дизайну рішення

У даному розділі наведено перелік компонент системи, які задіяні або потребують змін/створення в рамках реалізації функціональних вимог згідно з технічним дизайном рішення.

Компонент Службова назва Призначення / Суть змін

Сервіс Генератор

service-generation-utility

Генерація Java-проектів для сервісів

Схема розширених тегів Liquibase

liquibase-ext-schema

Валідація схеми

Модуль розширення тегів Liquibase

liquibase-ddm-ext

Обробка розширених тегів на етапі розгортання регламенту

7. Моделювання регламенту реєстру

7.1. Моделювання критеріїв пошуку

Адміністратору регламенту надається можливість обирати тип пагінації page при моделюванні критеріїв пошуку.

Структура регламенту реєстру
Зображення 1. Структура регламенту реєстру
Приклад конфігурації
    <changeSet author="registry owner" id="create pageable SC factor_chemical_host_contains_name">
        <ext:createSearchCondition name="factor_chemical_host_contains_name_pageable"  pagination="page">
            <ext:table name="factor" alias="f">
                <ext:column name="factor_id"/>
                <ext:column name="name" sorting="asc" searchType="contains"/>
            </ext:table>
            <ext:where>
                <ext:condition tableAlias="f" columnName="factor_type" operator="eq" value="'Хімічний: ГОСТ'"/>
            </ext:where>
        </ext:createSearchCondition>
    </changeSet>

Для адміністратора регламенту також доступні опції offset та none в атрибуті pagination.

offset - дає той самий результат що і true в поточній реалізації і є опцією за замовчанням.

none - дає той самий результат що і false в поточній реалізації.

Опції true та false стають застарілими і можуть бути видалені з часом. Але наразі, в наявних регламентах реєстрів вони продовжать працювати так само як і в поточній реалізації.

7.2. Валідація регламенту реєстру

В рамках реалізації рішення, необхідно розширити xml схему розширених тегів liquibase по якій проходить валідація.

8. Високорівневий план розробки

8.2. План розробки

  • Розширення схеми розширених тегів Liquibase.

  • Розширення модуля розширення тегів Liquibase.

  • Розширення сервіс генератору.

  • Розробка інструкцій для розробника регламенту та референтних прикладів.