Каталог решений - Пагинация в 1С

Пагинация в 1С

Пагинация в 1С

В наличии

Те, кому приходилось делать REST API на базе HTTP-сервисов 1С, могли в какой-то момент столкнуться с необходимостью разработки методов, которые позволяли бы возвращать данные с пагинацией, т.е. последовательными порциями.

В языках общего назначения пагинация реализуется простым использованием операторов OFFSET и LIMIT в SQL-запросе к базе данных. В языке запросов 1С оператора OFFSET нет, поэтому всем приходится решать эту задачу обходными способами.

Один из таких обходных способов представлен в этой статье.

Категория:

Описание

Предпосылки разработки методов API с пагинацией

В нашей компании разрабатывался сайт на собственном движке, и поскольку источником всех данных для него была учётная система на платформе 1С, а в штате было два программиста 1С, в качестве бэкенда было принято решение разработать отдельную систему на той же 1С.

Весь необходимый API был описан в формате Swagger (OpenAPI) руководителем проекта разработки сайта, его методы мы реализовали с помощью HTTP-сервисов 1С.

Метод API для получения номенклатуры для сайта изначально не предполагал никаких отборов, т.к. до какого-то момента выполнялся за приемлемое время, но спустя несколько месяцев из-за увеличившегося количества номенклатуры и связанных с ней данных метод стал выполняться очень долго, клиент не дожидался ответа.

С таймаутами заморачиваться не стали, т.к. они и так были установлены достаточно большими, по 300 секунд.

Решили сделать версию 2 того же метода, но уже с возможностью пагинации.

 

Особенности реализации пагинации средствами 1С

При разработке методов с пагинацией нужно учитывать следующие особенности:

  1. В языке запросов 1С нет оператора OFFSET, соответственно, смещение записей для получения определённой порции данных нужно реализовать как-то иначе.
    Ограничить количество записей можно с помощью оператора ВЫБРАТЬ ПЕРВЫЕ {количество объектов в порции}, тут всё очевидно.
    Разве что количество объектов в порции придётся подставлять через СтрШаблон(), СтрЗаменить() или конкатенацию.
    Но как выбрать только записи, начиная с определённой?
    Логичным решением выглядит нумерация записей и последующий отбор по номеру.
    В запросах 1С доступна функция АВТОНОМЕРЗАПИСИ(), которая последовательно присваивает номер записи, начиная с 1, полю с вызовом этой функции.
    А дальше по этому номеру можно отобрать нужную порцию данных.
    Это позволит не выбирать все данные с последующим получением нужных данных в коде, например, по индексам, а получать сразу готовую коллекцию записей с помощью запроса.
     
  2. Запросы к методу с одними и теми же полями "limit" (количество объектов в порции данных) и "next"* (номер первого объекта следующей порции) в теле запроса всегда** должны возвращать один и тот же набор объектов.
    * Названия полей приведены так, как они указаны у нас, вы можете их называть, разумеется, на ваше усмотрение.
    ** Передача тела запроса предполагает запрос POST, т.е. об идемпотентности тут речи нет, но метод, возвращающий разные результаты при одних и тех же параметрах запроса, должен вызывать вопросы у клиента. Для большей очевидности (в плане ожидания идемпотентности) можно было бы реализовать метод GET с параметрами в строке запроса, но мы пошли по пути POST с телом JSON.

    Тут тоже всё вроде бы очевидно: данные должны быть отсортированы, чтобы одни и те же номера всегда присваивались одним и тем же записям.
    Для этого лучше всего подходит код элемента в справочнике, т.к. коды в справочниках никто при нормальном учёте не меняет, а уникальный идентификатор нового объекта теоретически может быть сгенерирован таким, что при сортировке по ссылке новый элемент справочника попадёт куда-то в середину списка. Если ошибаюсь, поправьте, пожалуйста.
     
  3. Запросы к методу должны возвращать именно запрошенное (или меньшее) количество записей.

    Хотя левое соединение с другими таблицами может приводить к увеличению количества записей, изначально было не вполне очевидно, что возвращаемое методом количество записей может быть больше запрашиваемого.
    Чтобы этого избежать, основные данные предварительно нужно получать отдельно в запрашиваемом количестве и только потом связывать с дополнительными данными. В последней порции данных может быть меньше.
    Из-за того, что данные временных таблиц в общем случае*** упорядочивать нельзя, связывание основных данных с дополнительными нужно выполнять в дополнительном запросе.
    *** Можно в случае использования оператора ВЫБРАТЬ ПЕРВЫЕ.

 

Пример реализации

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

Многоточием в тексте запросов обозначены прочие поля.

В первом запросе получаем, фактически, все записи таблицы. Дополнительно не оптимизировали, т.к. отрабатывает быстро, да и клиент у этого метода всего один.

 

has been added to your cart:
Оформление заказа