Пример 1. Работа с простыми файлами, фильтрами, сортировкой

Описание задачи

Создать файл с заданием для обработки данных следующим образом:

  1. Прочитать данные из нескольких файлов.
  2. Объединить считанные потоки данных.
  3. Скопировать получившийся поток данных в несколько потоков.
  4. Вывести один из потоков в файл.
  5. Записи из второго потока отсортировать.
  6. Затем отфильтровать.
  7. Полученные данные записать в файл.

На рисунке ниже представлено графическое представление такого графа:

Отображение графа example_01.grf в инспекторе заданий

Заполнение файла задания

В начале создания файла нужно объявить, что его содержимое является заданием-графом, для этого открываем тег <Graph>.

Далее нужно открыть тег <Global>, в котором будут описаны метаданные и параметры графа.

Далее открываем элемент <Record>, атрибутами которого можно назначить fieldDelimiter – для объявления разделителя полей записи, и recordDelimiter – для указания символа, разделяющего записи.

Дочерним элементу <Record> является пустой элемент <Field>, у которого нет закрывающего тега. Его используем, чтобы указать имя (name) и тип данных (type) для полей записей.

Теперь поочередно закрываем теги </Record>, </Metadata> и </Global>.

Следующий открывающий тег - <Phase> с атрибутом number, указывающим номер фазы для определения очередности выполнения шагов. В этом примере фаза всего одна, ее номер можно не указывать.

Далее открываем три пустых элемента <Node>, атрибуты которых, описывают имя шага (id), входные и выходные файлы для шагов чтения и записи (file), типы шагов (type) и координаты для отрисовки шагов в инспекторе задач.

У элемента <Node> может быть дочерний элемент <Attr>, которому нужно задать имя name, а внутри записать логическое выражение для фильтрации или метод преобразования данных.

Еще нужно указать пустые теги <Edge> для описания ребер графа. В атрибутах этого элемента можно пояснить, какими ребрами какие шаги связать в этом графе и указать ссылку на метаданные, указанные в начале файла в теге <Metadata>.

В конце закрываем элементы </Phase> и </Graph>.

Получился файл задания:

<Graph>
    <Global>
        <Metadata id="ObjectWithPos">
            <Record fieldDelimiter="|" recordDelimiter="\n">
                <Field name="a" type="string"/>
                <Field name="b" type="integer"/>
                <Field name="c" type="float"/>
            </Record>
        </Metadata>
    </Global>
    
    <Phase number="0">
        <Node id="reader0" guiX="50"   guiY="100" guiName="FlatFileReader0" fileURL="data-in/others/example_01_in1.txt"   type="FLAT_FILE_READER"/>
        <Node id="reader1" guiX="50"   guiY="300" guiName="FlatFileReader1" fileURL="data-in/others/example_01_in2.txt"   type="FLAT_FILE_READER"/>
        <Node id="writer0" guiX="600"  guiY="100" guiName="FlatFileWriter0" fileURL="data-out/others/example_01_out1.txt" type="FLAT_FILE_WRITER"/>
        <Node id="writer1" guiX="600"  guiY="200" guiName="FlatFileWriter1" fileURL="data-out/others/example_01_out2.txt" type="FLAT_FILE_WRITER"/>
        <Node id="concat"  guiX="250"  guiY="200" guiName="Concat" type="CONCAT"/>
        <Node id="copy"    guiX="450"  guiY="200" guiName="Copy" type="SIMPLE_COPY"/>
        <Node id="sort"    guiX="650"  guiY="300" guiName="FileSortNode" sortKey="c(d)" type="EXT_SORT"/><!--"d" - descending-->
        
        <Node id="filter"  guiX="850" guiY="300" guiName="FilterNode" type="FILTER">
            <Attr name="filterExpression">
                <![CDATA[
                    $in[0].b > 0
                ]]>
            </Attr>
        </Node>
    
        <Edge id="edge0" fromNode="reader0:0" toNode="concat:0"/>
        <Edge id="edge1" fromNode="reader1:0" toNode="concat:1"/>
        <Edge id="edge2" fromNode="concat:0"  toNode="copy:0"/>
        <Edge id="edge6" fromNode="copy:0"    toNode="writer1:0" metadata="ObjectWithPos"/>
        <Edge id="edge5" fromNode="copy:1"    toNode="sort:0"/>
        <Edge id="edge3" fromNode="sort:0"    toNode="filter:0"/>
        <Edge id="edge4" fromNode="filter:0"  toNode="writer0:0" metadata="ObjectWithPos"/>
    </Phase>
</Graph>

Результат

На вход были поданы два файла:

файл 1:

werwr|234|25.45
krlgkrgw|63|-65.8
srgehdhdfxyjset___g_jgsn|72465|92745972
fbsb!efb|-42536356|0
glsdgh|453453|4524.545

файл 2:

Лёша на горе рога нашёл|-123|-123
Около Мити молоко|234|454.4
Тина барабанит|12|12.12

На выходе получены файлы:

файл 1 (содержит результат работы задания целиком):

glsdgh|453453|4524.545
werwr|234|25.45
Тина барабанит|12|12.12
fbsb!efb|-42536356|0.0
krlgkrgw|63|-65.8

файл 2 (содержит результат конкатенации двух потоков данных на втором шаге задания):

werwr|234|25.45
krlgkrgw|63|-65.8
srgehdhdfxyjset___g_jgsn|72465|92745970.0
fbsb!efb|-42536356|0.0
glsdgh|453453|4524.545
Лёша на горе рога нашёл|-123|-123.0
Около Мити молоко|234|454.4
Тина барабанит|12|12.12

Атрибуты используемых шагов

Атрибуты FlatFileReader:

АтрибутОбязательныйОписаниеВозможные значения
idдаНазвание шага для указания в атрибутах ребра fromNode и toNode. Может быть произвольным.id="reader"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="FlatFileReader"
fileнетПуть к источнику данных для чтенияfile="data-in/others/example_01_in1.txt"
typeдаТип шага. Определяет функциональность данного шага.type="FlatFileReader"

Атрибуты Concat:

АтрибутОбязательныйОписаниеВозможные значения
idдаНазвание шага для указания в атрибутах ребра fromNode и toNode. Может быть произвольным.id="concat"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="Concat"
typeдаТип шага. Определяет функциональность данного шага.type="Concat"

Атрибуты Copy:

АтрибутОбязательныйОписаниеВозможные значения
idдаНазвание шага для указания в атрибутах ребра fromNode и toNode. Может быть произвольным.id="copy"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="Copy"
typeдаТип шага. Определяет функциональность данного шага.type="Copy"

Атрибуты FileSortNode:

АтрибутОбязательныйОписаниеВозможные значения
idдаНазвание шага для указания в атрибутах ребра fromNode и toNode. Может быть произвольным.id="sort"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="FileSortNode"
sortKeyда

Имя поля для ключа и порядок сортировки.

«d» - «descending» - по убыванию

«a» - «ascending» - по возрастанию

sortKey="component(d)"
typeдаТип шага. Определяет функциональность данного шага.type="FileSortNode"

Атрибуты FilterNode:

АтрибутОбязательныйОписаниеВозможные значения
idдаНазвание шага для указания в атрибутах ребра fromNode и toNode. Может быть произвольным.id="filter"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="FilterNode"
Filter expressionдаВыражение, по которому фильтруются записи. Возвращает логическое значение.
<Attr name="filterExpression">
    <![CDATA[
        $in[0].Product == "карандаш"
    ]]>
</Attr>
typeдаТип шага. Определяет функциональность данного шага.type="FilterNode"

Атрибуты FlatFileWriter:

АтрибутОбязательныйОписаниеВозможные значения
idнетНазвание шага для использования в атрибутах ребра fromNode и toNode.id="writer"
guiXнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiX="50"
guiYнетКоордината верхнего левого угла шага для отрисовки графа в инспекторе заданий.guiY="100"
guiNameнетИмя шага, указываемое на графе. Равно type шага. Нельзя изменять.guiName="FlatFileWriter"
file URLдаПуть к файлу, в который должен быть записан результирующий набор данных.${WRITE_DIR}/out.txt
typeдаТип шага. Определяет функциональность данного шага.type="FlatFileWriter"