Как получить данные по списку товаров через HTTP-сервис 1С за один запрос

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции различных систем на базе 1С:Предприятие часто возникает задача получения оперативных данных, например, остатков товаров или цен из другой информационной базы. Использование метода GET для получения данных по одному объекту (через передачу идентификатора в параметрах строки запроса) удобно и просто в реализации, однако оно перестает быть эффективным, когда количество объектов исчисляется сотнями или тысячами. Выполнение 100 отдельных HTTP-запросов в цикле создаст огромную нагрузку на сеть и сервер, а также значительно увеличит время ожидания для пользователя.

В данной статье мы разберем, как оптимизировать этот процесс, реализовав пакетную передачу данных в одном запросе. Мы рассмотрим использование метода POST, работу с форматом JSON, сериализацию данных и методы оптимизации на стороне базы-источника.

Переход от GET к методу POST

Для начала проанализируем ситуацию: почему GET нам не подходит для пакетной передачи? Основное ограничение GET заключается в том, что параметры передаются в URL-строке, которая имеет лимит по длине. Кроме того, передавать сложные структуры данных через параметры строки крайне неудобно.

Решением является использование метода POST. В этом случае данные передаются не в заголовке или строке адреса, а в теле (body) запроса. Это позволяет передать практически неограниченный объем информации в структурированном виде (например, JSON или XML).

Подготовка данных: Сериализация таблицы в JSON

Рассмотрим наиболее популярный и универсальный способ обмена — формат JSON. Если в вашей табличной части 100 строк, содержащих ссылки на номенклатуру и характеристики, напрямую передать объект ТаблицаЗначений через ЗаписатьJSON() не получится, так как этот объект не является сериализуемым по умолчанию для данного метода.

Выясним, как правильно подготовить данные для отправки. Самый надежный способ — преобразовать таблицу в Массив, состоящий из Структур. Разберем по шагам, как это реализовать:


// Создаем массив для хранения данных строк
СписокТоваров = Новый Массив;

Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    ДанныеТовара = Новый Структура;
    ДанныеТовара.Вставить("НоменклатураGUID", Строка(СтрокаТЧ.Номенклатура.УникальныйИдентификатор()));
    ДанныеТовара.Вставить("ХарактеристикаGUID", Строка(СтрокаТЧ.Характеристика.УникальныйИдентификатор()));
    
    СписокТоваров.Добавить(ДанныеТовара);
КонецЦикла;

// Сериализуем массив в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СписокТоваров);
СтрокаЗапроса = ЗаписьJSON.Закрыть();

В данном примере мы преобразуем ссылки 1С в их строковое представление GUID. Это гарантирует, что на стороне получателя мы сможем однозначно идентифицировать объекты, даже если типы данных в базах различаются. Использование Структуры позволяет легко добавлять новые поля (например, склад или количество) без изменения логики парсинга.

Оптимизация поиска на стороне сервера

Теперь проанализируем, как эффективно обработать полученный массив на стороне HTTP-сервиса (базы-источника остатков). Получив JSON, мы десериализуем его обратно в массив структур. Чтобы запрос к базе данных отработал максимально быстро, крайне не рекомендуется выполнять поиск остатков в цикле.

Вместо этого мы применим следующий алгоритм:

  1. Выгрузим полученный массив данных во временную таблицу в запросе.
  2. Выполним соединение этой временной таблицы с виртуальной таблицей остатков РегистрНакопления.ТоварыНаСкладах.Остатки.
  3. Сгруппируем данные и вернем результат одним пакетом.

Посмотрим на пример формирования запроса на стороне сервера:


// Предположим, МассивДанных получен из ЧтенияJSON
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВТ_Данные.НоменклатураGUID КАК НоменклатураGUID,
    |	ВТ_Данные.ХарактеристикаGUID КАК ХарактеристикаGUID
    |ПОМЕСТИТЬ ВТ_Запрос
    |ИЗ
    |	&ТЗ_Данные КАК ВТ_Данные
    |;
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток,
    |	ВТ_Запрос.НоменклатураGUID КАК НоменклатураGUID,
    |	ВТ_Запрос.ХарактеристикаGUID КАК ХарактеристикаGUID
    |ИЗ
    |	ВТ_Запрос КАК ВТ_Запрос
    |		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
    |				,
    |				(Номенклатура.УникальныйИдентификатор, Характеристика.УникальныйИдентификатор) В
    |					(ВЫБРАТЬ
    |						ВТ.НоменклатураGUID,
    |						ВТ.ХарактеристикаGUID
    |					ИЗ
    |						ВТ_Запрос КАК ВТ)) КАК ТоварыНаСкладахОстатки
    |		ПО ВТ_Запрос.НоменклатураGUID = ТоварыНаСкладахОстатки.Номенклатура.УникальныйИдентификатор";

Важный момент: поиск по строковому представлению GUID в больших базах может быть медленным. Если производительность критична, рекомендуется предварительно конвертировать строковые GUID в ссылки в самой базе-источнике или использовать соответствия (Maps).

Альтернативный метод: Использование Хранилища Значения

Если обе базы являются базами 1С и имеют идентичные или схожие структуры, рассмотрим метод передачи через ХранилищеЗначения. Этот способ позволяет передать объект ТаблицаЗначений целиком, сохраняя типизацию колонок и используя встроенное сжатие данных.

Разберем процесс по шагам:

  1. На стороне отправителя помещаем таблицу в ХранилищеЗначения с максимальным сжатием.
  2. Получаем ДвоичныеДанные из хранилища.
  3. Передаем эти данные в теле POST-запроса.
  4. На стороне получателя читаем тело запроса как двоичные данные, восстанавливаем хранилище и извлекаем таблицу.

// Код на стороне отправителя
Хранилище = Новый ХранилищеЗначения(ТаблицаТоваров, Новый СжатиеДанных(9));
ДвоичныеДанныеТела = Хранилище.Получить();
// Далее передаем ДвоичныеДанныеТела в HTTPЗапрос.УстановитьТелоИзДвоичныхДанных()

Этот метод считается одним из самых быстрых для сценария "1С -> 1С", так как исключает стадию текстового парсинга JSON или XML.

Дополнительные рекомендации по производительности

Проанализируем еще несколько технических нюансов, которые помогут сделать ваш HTTP-сервис профессиональным:

1. Сжатие GZIP. Если вы передаете очень большие списки (тысячи строк), объем текстового JSON может быть значительным. Используйте сжатие GZIP. В 1С это реализуется через объект ЗаписьДанных и СжатиеДанных. Большинство современных HTTP-сервисов умеют прозрачно работать со сжатым контентом, если указаны соответствующие заголовки Content-Encoding: gzip.

2. Использование соответствий (Соответствие). Как было предложено в обсуждении, на стороне отправителя можно сформировать Соответствие, где ключом будет комбинированная строка "GUID_Номенклатуры + GUID_Характеристики", а значением — необходимый параметр. Объект Соответствие нативно сериализуется в 1С и удобен для быстрого поиска значения по ключу после получения ответа.

3. Обработка ошибок. Всегда проектируйте структуру ответа так, чтобы она содержала статус выполнения. Например, возвращайте структуру с полями Success (булево) и Data (массив результатов). Это позволит вызывающей базе корректно обработать ситуацию, когда, например, по части товаров остатки найдены, а по части — произошла ошибка в данных.

Подводя итог, можно сказать, что для получения данных по списку товаров оптимальным выбором будет POST-запрос с передачей массива структур в формате JSON. Это обеспечивает гибкость, наглядность при отладке и высокую скорость работы за счет минимизации количества сетевых вызовов.

← На главную