Работа с переменными в Loginom

Переменные предназначены для гибкой настройки логики обработки данных. Они позволяют задавать параметры выполнения и применимы для большинства компонентов платформы. Рассмотрим различные примеры использования переменных для решения практических задач.

Переменная — это один из видов информации, которая может передаваться между узлами. Она представляет собой именованный объект, содержащий единственное значение определенного типа.

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

Рассмотрим решение нескольких задач в Loginom с использованием переменных.

Логирование

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

Для этого можно использовать предопределенные переменные. Они создаются автоматически и хранят информацию, которая не зависит от сценария обработки.

Например, в переменных сессии в UserName содержится логин пользователя, открывшего сценарий. А в переменной SessionGuid уникальный идентификатор текущей сессии, который автоматически генерируется при каждом запуске. Эти переменные можно использовать для решения описанной выше задачи.

Сценарий Loginom

Это пример сценария, содержащий определенный результат обработки, загруженный ранее в файл, который необходимо экспортировать в другой файл с уникальным именем и с указанием в каждой строке выгружаемой таблицы пользователя, запустившего обработку.

Сначала при помощи Калькулятора к имеющейся таблице нужно добавить поле, содержащее логин пользователя — UserName. Он будет продублирован в каждой строке.

Добавление поля с логином пользователя

И на выходе получится следующий набор данных.

Добавление имени автора

В узле Калькулятор (переменные) нужно задать правило формирования уникального имени экспортируемого файла. Оно собирается по следующему принципу: из Переменных пакета берется путь, в котором лежит пакет, из Переменных сессии уникальный Guid сессии, а в конце добавляется расширение файла. Это гарантирует, что при каждом запуске будет сформирован новый файл лога.

Уникальное имя экспортируемого файла

В настройках узла Экспорт файла в верхний порт надо подать подготовленные в узле Добавляем имя автора данные, а в нижний порт переменные из узла Выбор уникального имени.

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

Выбор уникального имени

Примечание: Для отображения управляющих переменных у многих узлов требуется в контекстном меню выбрать пункт «Показать порт управляющих переменных».

Таким образом, при помощи предопределенных переменных было сформировано уникальное имя файла и зафиксирован логин пользователя, который его запустил. В результате при каждом запуске сценария в папку, где расположен файл пакета, будет записываться новый лог.

Фильтрация данных

При решении задач часто требуется отфильтровать данные, которые удовлетворяют одному или нескольким условиям.

Чтобы задать условие фильтрации удобно использовать переменные сценария и стандартные компоненты для работы с переменными. С их помощью можно, например: задать категорию товаров или клиентов, выбрать город или страну, найти сумму, максимум или медиану столбца и использовать эти переменные для фильтрации.

Типичная задача может описываться следующим образом: отобрать группы товаров, проданных в определенном городе, количество продаж которых больше среднего для данного населенного пункта.

Ниже приведен пример сценария, с помощью которого эта задача была решена.

Сценарий

Сначала добавим переменную сценария, содержащую город для которого будут отобраны значения.

Добавление переменной

Узел Продажи содержит следующие данные:

Данные

В узел Отбор данных по городу передаем на вход исходные данные Продажи и переменную пользователя City. В поле значение для сравнения переключаемся на режим «значение параметра задается переменной». В появившемся списке выбираем переменную Город.

Отбор данных по городу

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

Группировка

Для расчета среднего количества проданных товаров по группам требуется передать сгруппированные значения в узел Нахождение среднего значения. Внутри этого узла перенести столбец количество в выбранные поля и изменить метод агрегации на среднее (по умолчанию стоит сумма).

Таблица в переменные

Передаем данные из узлов Группировка товаров и Нахождение среднего значения в узел Отбор данных. Отбираем те группы, где количество больше среднего, переключив «значение для сравнения» в режим «значение параметра задается переменной».

Отбор данных

На выходе получаем следующий набор данных:

Итоговые данные

Таким образом, с помощью переменных сценария задан город, для которого требуется отфильтровать данные. При необходимости проанализировать данные для другого города, требуется лишь изменить значение в переменной City. Также с помощью переменных было рассчитано и передано для отбора среднее значения поля.

Многократное использование логики

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

Для этого можно использовать переменные. Чтобы на входе подмодели появились переменные, нужно в настройках Подмодели в поле «входы» нажать «+» и выбрать Переменные, сохранить настройки, дважды щелкнуть на входном порту и добавить одну или несколько переменных.

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

Сценарий в подмодели

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

Входные переменные

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

Сумма за единицу товара

В узле Отбор клиентов передадим на вход данные и входные переменные Подмодели, чтобы задать условие фильтрации клиентов. Переключив режим в поле значение для сравнения, в появившемся списке выберем переменную Тип клиента.

Отбор клиентов

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

Группировка

Для отбора некоторого количества самых дорогих товаров следует их отсортировать по убыванию суммы. Делаем это в узле Сортировка по убыванию.

Сортировка

В узле Условие отбора товаров прописываем, что количество строк выходного набора должно быть меньше переменной подмодели Отбор, в которой прописывается сколько данных нужно отобрать. Всем строкам, идущим до отбора нужного количества, присваивается значение – True.

Условие отбора

В узле Отбор самых дорогих товаров оставляем данные, где поле Самые дорогие товары имеют значение — Истина.

Отбор самых дорогих товаров

На выходе из Подмодели имеем топ самых дорогих товаров, которые покупали постоянные клиенты:

Выбор постоянных клиентов

Для отбора данных для VIP клиентов, требуется только поменять значение переменной Тип клиента. В результате получаем список самых дорогих товаров, которые покупала данная группа клиентов:

Выбор VIP клиентов

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

Обращение к веб-сервису

В процессе обработки данных может потребоваться выполнить запрос к веб-сервису. Один из способов реализации — это обращение к нему из узла JavaScript с помощью интерфейса Fetch API.

Если необходимо веб-сервису передать параметры, например, дату, то это можно сделать через входной порт переменных узла JavaScript.

Для использования входной переменной внутри кода — нужно обратиться к ней через объект InputVariables. С помощью свойства Items этого объекта прочитать коллекцию входных переменных узла, выбрать имя входной переменной и через Value получить значение. Например: InputVariables.Items.NameVariables.Value.

В следующем сценарии решается задача получения курсов валют на определенную дату с веб-сервиса.

Сценарий

Для решения задачи в узел Парсим данные, передаются переменные, определяющие дату, на которую необходимо получить курсы валют.

Переменные

Узел Парсим данные содержит следующий код:

    import { InputVariables, OutputTable } from "builtIn/Data";

    import {fetch} from "builtIn/Fetch";

    // Добавляем переменные, которые принимают значения из входных портов
    let year = InputVariables.Items.year.Value;
    let month = InputVariables.Items.month.Value;
    let day = InputVariables.Items.day.Value;

    // Вывод в выходной набор данных
    OutputTable.Append();
    // Запрос на сервис: переменные используются для формирования URL
    fetch(`https://www.cbr-xml-daily.ru/archive/${year}/${month}/${day}/daily_json.js`)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}, 
                                statusText: ${response.statusText}`);
            }
            return response.text();
        })
        .then(text=> OutputTable.Set(0, text));

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


    import {InputTable, InputVariables, OutputTable} from "builtIn/Data";
    
    let txtJSON;
    let obj;
   
    // Функция вывода элемента JSON в выходной набор данных.
    // Принимает параметры:
    // id - идентификатор строки входного набора;
    // parent - parent элемента JSON;
    // key - идентификатор элемента JSON;
    // type - тип элемента JSON;
    // value - значение элемента JSON.
    function append(id, parent = null, key = null, type = null, value = null) {
    // Добавление новой строки в выходной набор.
        OutputTable.Append();
    // Установка значения заданного поля в добавленной строке.
        OutputTable.Set('id', id);
        OutputTable.Set('parent', parent);
        OutputTable.Set('key', key);
        OutputTable.Set('type', type);
        OutputTable.Set('value', value);
    }

    // Функция обработки объекта JSON.
    // Принимает параметры:
    // id - идентификатор строки входного набора;
    // o - объект JSON;
    // p - parent элемента JSON (по умолчанию = 'root').
    function get_elements(id, o, p = 'root') {
        let x;
    // Цикл по элементам JSON.
        for (let k in o) {
    // Переменная x принимает текущий элемент JSON.
            x = o[k];
    // Если элемент не имеет подчиненных,
    //то просто выводится в выходной набор данных функцией 'append(id, parent, key, type, value)'.
            if (typeof x != 'object' || x == null) {
                append(id, p, k, typeof x, x);
    // В противном случае: выводится в выходной набор
    // и передается на обработку подчиненных элементов рекурсивным вызовом данной функции.
            } else {
                append(id, p, k, typeof x);
                get_elements(id, x, p + ':' + k);
            }
        }
    }

    // Проверяем наличие данных во входном наборе.
    // Если табличный порт задействован, то обрабатываем данные этого порта.
    // В противном случае обрабатываем данные порта входных переменных.
    if (InputTable) {
    // Цикл по строкам входного набора.
        for (let j = 0, c = InputTable.RowCount; j < c; j++) {
    // Переменная txtJSON принимает текст JSON из поля 'txtJSON' входного набора.
            txtJSON = InputTable.Get(j, 'txtJSON');
    // Переменная obj принимает объект JSON
            obj = JSON.parse(txtJSON);
    // и далее передается в функцию обработки объекта JSON 'get_elements(id, o, p = 'root')'.
            get_elements(j, obj);
        }
    } else {
        console.log("Табличный порт не задействован");
    // Переменная txtJSON принимает текст JSON из переменной 'JSON' входного порта.
        txtJSON = InputVariables.Items.JSON.Value;
    // Если txtJSON содержит значение, то obj принимает объект JSON
        if (txtJSON) {
            obj = JSON.parse(txtJSON);
    // и далее передается в функцию обработки объекта JSON.
            get_elements('Порт переменных', obj);
        } else {
            console.log("Переменная  входного порта не задана")
        }
    }

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

Отбор данных с кодом валюты

В узле Преобразование таблицы превращаем данные в сводную таблицу для более наглядного вида.

Преобразование таблицы

В итоге получаем следующие данные о курсах валют на заданную дату:

Курсы валют

Таким образом, с помощью переменных внутрь кода компонента JavaScript была передана дата, на которую требовалось получить информацию о курсах валют с веб-сервиса. Точно также можно передавать переменные в узел Python.

Заключение

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

В статье были рассмотрены только несколько ситуаций, где применяются Переменные. Их также можно использовать для: тестирования и отладки веб-сервисов, запросов в Базы данных, задания условий Кластеризации и Сэмплинга и т.д.

Другие материалы по теме:

Отбор переменных в моделях линейной регрессии

Программирование в Loginom: Python vs JavaScript

Курс Loginom Skills «Основы работы в Loginom»

#loginom

Смотрите также