Фабрика данных Azure — действие копирования, если файл не найден в таблице базы данных

#azure #azure-data-factory #azure-data-factory-2

Вопрос:

Я пытаюсь скопировать данные из csv файлов, найденных в Azure Datalake, в таблицу в SQL Server. В качестве условия я хочу копировать файлы, которых еще нет в базе данных, только с помощью столбца имени файла, найденного в таблице базы данных. Ниже приведена моя попытка (я не смог найти пример этого в Интернете).

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

введите описание изображения здесь

Вот результаты деятельности Get Metadata и. Lookup

Вывод метаданных файлов сбора данных

 {
    "childItems": [
        {
            "name": "surveydetails_eq5d_001.csv",
            "type": "File"
        },
        {
            "name": "surveydetails_koos_001.csv",
            "type": "File"
        },
        {
            "name": "surveydetails_oxford_001.csv",
            "type": "File"
        },
        {
            "name": "surveydetails_womac_001.csv",
            "type": "File"
        }
    ],
 

Поиск файла таблицы базы данных

 {
    "count": 4,
    "value": [
        {
            "file_name": "surveydetails_koos_001.csv"
        },
        {
            "file_name": "surveydetails_oxford_001.csv"
        },
        {
            "file_name": "surveydetails_eq5d_001.csv"
        },
        {
            "file_name": "surveydetails_womac_001.csv"
        }
    ],
 

Как только у меня будут имена файлов, я использую a ForEach и повторяю элементы Datalake:

 @activity('Datalake Files Metadata').output.childitems
 

Внутри у ForEach меня есть IfCondition приложение, которое проверяет, находится ли текущий файл Datalake в массиве поиска. Если файла Datalake нет в массиве, выполняется операция копирования. Однако с помощью этой конструкции я бы не ожидал, что что-то будет скопировано, так как элементы в datalake уже находятся в базе данных. У меня такое чувство, что динамический контент в IfCondition нем отключен, но после поиска в Интернете в течение последних нескольких часов я не могу найти никаких очевидных ошибок. Есть ли логика в выключении IfCondition? Это что-то другое? Пожалуйста, помогите.

Логика для IfCondition :

@not(contains(activity('Database Table File Lookup').output.value, item().name))
введите описание изображения здесь

Комментарии:

1. Отличный вопрос! Очень подробно. У меня похожая проблема. Надеюсь, вы скоро получите ответ 😉

Ответ №1:

Логика Ifcondition содержит элемент().name, который возвращает строку, равную имени файла(Пример —> «surveydetails_eq5d_001.csv»).

Однако действие(«Поиск файла таблицы базы данных»). output.value возвращает массив словарей. В словарях есть «имя_файла» имя файла. то есть

 [
        {
            "file_name": "surveydetails_eq5d_001.csv"
        },
        {
            "file_name": "surveydetails_koos_001.csv"
        },
        {
            "file_name": "surveydetails_oxford_001.csv"
        },
        {
            "file_name": "surveydetails_womac_001.csv"
        }
]
 

Вот почему условие IF не выполняется.

Что вы можете попробовать, так это создать 2 новых массива переменных dblist и mytemparray. Выполните итерацию по массиву действия («Поиск файла таблицы базы данных»). вывод.значение и извлеките каждое имя файла в свой новый массив dblist(для этого вы можете использовать «объединение»). Затем вы можете использовать этот массив в своей проверке Ifcondition. Не забудьте установить переключатель «Последовательный» в положение ВКЛ в цикле for. Смотрите снимок экрана.введите описание изображения здесь

Внутри моего цикла for у меня есть 2 набора переменных действий.

  1. Упражнение 1 : Скопируйте список dblist в mytemparray
  2. Действие 2 : Объедините mytemparray с именем файла и сохраните в dblist @union(переменные(‘mytemparray’),массив(элемент().имя файла))

Комментарии:

1. Полезно, но сложность циклов не идеальна.

Ответ №2:

Основываясь на некоторой информации Microsoft о выражениях и комментарии @anupam, я преобразовал массив в строку, чтобы сравнить строку с подстрокой. Это упрощает ответ @Anupams, потому что другой forEach ответ не требуется.

 @not(contains(string(activity('Survey Details File Lookup').output.value), item().name))