Top.Mail.Ru

Загрузка номенклатуры из JSON в 1С: от «запроса в цикле» до оптимизированного решения

В данной статье сделаем разбор задачи по загрузке файла JSON в 1С, в справочник Номенклатура, с табличной частью. Подобного рода задачи могут попадаться на собеседованиях, в качестве тестовых заданий, либо в качестве практических задач для самостоятельной подготовки. По секрету скажу, что настоящие «боевые» JSON файлы, и соответственно, задачи — бывают куда сложнее.

Условия задачи

  1. Сделать обработку по заполнению справочника Номенклатура из файла JSON.
  2. Файл должен выбираться через диалог выбора файла.
  3. Сопоставление товара по артикулу, предусмотреть повторную загрузку, исключить возможность создания дублей.
  4. Для новых товаров — заполняем все данные, для найденных уже существующих — только обновляем описание.
  5. Проверку наличия номенклатуры в базе необходимо производить запросом.
  6. Проверку изменения описания номенклатуры (в файле поле «description») производить также запросом.
{
  "ART-123.X": {
    "name": "Беспроводные наушники Pro",
    "brand": "SoundTech",
    "description": "Высококачественный звук с активным шумоподавлением и до 30 часов работы.",
    "components": [
      {
        "id": "CMP-01",
        "partName": "Аккумулятор",
        "quantity": 1
      },
      {
        "id": "SPK-L-02",
        "partName": "Динамик левый",
        "quantity": 2
      }
    ]
  },
  "SKU_456.B": {
    "name": "Механическая клавиатура",
    "brand": "KeyMaster",
    "description": "RGB подсветка, переключатели Blue, алюминиевый корпус."
  },
  "MDL.789-A": {
    "name": "Умные часы FitBand",
    "brand": "WearTech",
    "description": "Мониторинг пульса, GPS, водозащита IP68.",
    "components": [
      {
        "id": "BATT-99",
        "partName": "Зарядный модуль",
        "quantity": 1
      }
    ]
  }

Обзор решения

Не будем тут подробно останавливаться на том, как сделать обработку, добавить кнопку, прочитать файл через ПоместитьФайлНаСерверАсинх с диалогом выбора файла. Наша основная цель — проанализировать JSON и понять, как его правильно читать и обрабатывать.

Неявные моменты

Внимательно посмотрим на структуру JSON файла. Мы видим, что это не обычный массив, а словарь — т.е. корневой объект, свойства которого — в свою очередь тоже объекты.

Теперь к ключам самих свойств. Во первых, можно сделать предположение, что значения этих свойств и являются артикулами. Во-вторых, как видим, на примере «ART-123.X» — артикулы могут содержать спец. символы, а следовательно, прочитать в структуру мы их не сможем. Делаем себе пометку, что читать будем в соответствие.

Еще один подводный камень — поле «description», по-русски — «описание». Судя по тому, что там достаточно длинные строки, и в условии задачи их длина не ограничена, будем считать, что это поле может содержать строки произвольной длины. А раз так, то в запросе мы не сможем их явным образом сравнить с данными базы, и придется что-то изобретать.

Ошибка, которую часто допускают при сопоставлении данных базы с JSON

Достаточно часто встречаются решения, что называется, «в лоб» — прочитали JSON, получили коллекцию объектов, и начинаем ее перебирать. Каждый объект запросом ищем в базе по ключевым полям — в нашем случае, по артикулу. Потом при необходимости создаем объект, заполняем ему таб. часть, и записываем. А если элемент найден, дополнительно надо сравнить описание, и если описания не совпадают — обновить и так же записать. Схематично такое решение изображено на рисунке ниже. И тут мы получим что? Получим мы — запрос в цикле, что крайне не эффективно с точки зрения производительности, т.к. мы выполним этот запрос столько раз, сколько объектов в нашей коллекции. А если их тысяча? Сто тысяч? Миллион? На масштабе становится понятна неоптимальность такого подхода.

Как оптимизировать решение?

В идеале, мы бы хотели выполнить все за один запрос к базе данных, за один заход сопоставив номенклатуру по артикулам, откинув лишние элементы и оставив только те которые надо создать или обновить.
Но для такого решения ни соответствие, ни структура, ни массив не подойдут — их в запрос не запихнуть. Значит, надо каким-то образом перегнать данные в таблицу значений. При этом, табличные части components нас до поры не интересуют — их можно сложить в отдельное соответствие с ключами по артикулам, а потом по ключам быстро найти нужную таблицу — только для тех элементов Номенклатуры, которые будем создавать.

Важный нюанс! Таблица значений должна быть с типизированными колонками, чтобы запросом можно было ее прочитать.

А что же делать со сравнением поля description?

А тут можно использовать  «секретный ингридиент» в виде хеширования. Будем использовать объект ХешированиеДанных, и в принципе, почти любую функцию хеширования, например md5. Там, конечно есть нюансы — в зависимости от функции хеширования, хеш-сумма будет либо двоичными данными, либо числом. Двоичные данные прекрасно можно превратить в строку, и записать в базу данных при создании номенклатуры. а при обновлении — вычислить хеш входящего поля description, дополнить этим хешем нашу промежуточную таблицу значений, и уже в запросе можно будет прекрасно делать сравнение на неравенство.

Заключение

За счет использования промежуточной таблицы значений мы можем избавиться от запроса в цикле и одним запросом сопоставить номенклатуру по артикулу. А за счет использования хеширования поля «description» мы можем сколь угодно большую строку преобразовать к компактной хеш-сумме, и также в том же запросе сравнить с данными в базе.
Это позволит нам многократно уменьшить количество  обрабатываемых объектов — оставим только новые или те, где описание не совпадает.

Для самых терпеливых молодцов

Ну и раз уж вы добрались до конца статьи, и хотели бы узнать полное решение с примером, который можно скачать и поковырять в конфигураторе.
Полное видео с решением данной задачи, а также файл конфигурации с примером и файл  JSON для загрузки есть в моем закрытом Клубе для разработчиков. Буду рад видеть вас в числе резидентов Клуба!

Оставьте комментарий

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