【问题标题】:Check if all files are available in storage - Azure ADF检查存储中是否所有文件都可用 - Azure ADF
【发布时间】:2022-02-09 06:51:06
【问题描述】:

在 Azure 数据工厂中,如何检查字符串(文件名)数组是否包含值?

我正在从获取元数据活动中获取文件名,我需要在继续之前检查我拥有的所有 4 个文件名在存储帐户中是否可用。

我希望存储帐户中有 4 个文件,我需要检查所有 4 个文件是否都可用。我需要明确检查文件名而不是文件数 - 这是一项要求

当我尝试使用 get meta data 中的子项对其进行验证时,我收到错误 "array elements can only be selected using an integer index." 这里的问题是该文件可能会在下一次加载时出现在任何索引处

有没有更好的方法来验证文件名?

感谢您的帮助,在此先感谢

【问题讨论】:

    标签: azure-data-factory azure-data-factory-2 azure-data-factory-pipeline azure-adf


    【解决方案1】:

    可以使用数组检查是否存在多个文件,但这有点繁琐。我经常将其传递给管道中的另一个活动,例如存储过程或笔记本活动,具体取决于您在管道中可用的计算(例如 SQL 数据库或 Spark 集群)。但是,如果您确实需要在管道中执行此操作,这可能对您有用。

    首先,我有一个具有以下值的数组参数:

    Parameter Name Parameter Type Parameter Value
    pFilesToCheck Array ["json1.json","json2.json","json3.json","json4.json"]

    这些是必须存在的文件。接下来我有一个 Get Metadata 活动指向一个数据湖文件夹,并在字段列表中设置了 Child Items 参数:

    这将以这种格式返回一些输出,列出给定目录中的所有文件,以及一些关于执行的附加信息:

    {
        "childItems": [
            {
                "name": "json1.json",
                "type": "File"
            },
            {
                "name": "json2.json",
                "type": "File"
            },
            {
                "name": "json3.json",
                "type": "File"
            },
            {
                "name": "json4.json",
                "type": "File"
            }
        ],
        "effectiveIntegrationRuntime": "AutoResolveIntegrationRuntime (Some Region)",
        "executionDuration": 0,
        "durationInQueue": {
            "integrationRuntimeQueue": 1
        },
        "billingReference": {
            "activityType": "PipelineActivity",
            "billableDuration": [
                {
                    "meterType": "AzureIR",
                    "duration": 0.016666666666666666,
                    "unit": "Hours"
                }
            ]
        }
    }
    

    为了比较输入数组pFilesToCheck必须存在的文件)与Get Metadata活动的结果(确实存在的文件) ,我们必须将它们放在可比较的格式中。我使用 Array 变量来执行此操作:

    Variable Name Variable Type
    arrFilenames Array

    接下来是一个For Each活动,以顺序模式运行,并使用range函数从0循环到3,即childItems数组中每个项目的数组索引。该表达式确定Get Metadata 输出中的项目数 这是从0开始的。 Items 属性设置为以下表达式:

    @range(0,length(activity('Get Metadata File List').output.childItems))
    

    For Each 活动内部是一个Append 活动,它将for each 循环中的当前项附加到数组变量arrFilenames。它在 Value 属性中使用此表达式:

    @activity('Get Metadata File List').output.childItems[item()].name
    

    '@item()' 在这种情况下将是一个介于 0 和 3 之间的数字,由上面提到的 range 函数生成。循环完成后,数组arrFilenames 现在将如下所示(即与输入数组格式相同):

    ["json1.json","json2.json","json3.json","json4.json"]
    

    现在可以使用intersection 函数比较输入数组和实际文件列表。我使用带有布尔变量的Set Variable 活动来记录结果:

    @equals(
    length(variables('arrFilenames')),
    length(intersection(variables('arrFilenames'),pipeline().parameters.pFilesMustExist)))
    

    这个表达式比较包含实际存在的文件的数组的长度通过交集函数连接到应该存在的文件的输入数组的同一数组的长度。如果数字匹配,则所有文件都存在。如果数字不匹配,则所有文件都存在。

    【讨论】:

    • 这是一个很好的答案。对于我的用例——确定容器是否包含指定的文件列表——我必须将最终的 Set Variable 调整为:@equals( length(pipeline().parameters.pFilesMustExist), length(intersection(variables('arrFilenames'),pipeline().parameters.pFilesMustExist)))
    【解决方案2】:

    我的获取元数据输出如下所示

     "childItems": [
        {
            "name": "1.py",
            "type": "File"
        },
        {
            "name": "SalesData.numbers",
            "type": "File"
        },
        {
            "name": "file1.txt",
            "type": "File"
        }
    

    ]

    我在设置变量活动中使用以下表达式来检查文件名

    @if(
    contains(activity('Get Metadata1').output.childitems,
    json(concat('{"name":"file1.txt"',',','"type":"File"}'))), 
    
    if(
    contains(activity('Get Metadata1').output.childitems,
    json(concat('{"name":"file2.txt"',',','"type":"File"}'))),
    
    if(
    contains(activity('Get Metadata1').output.childitems,
    json(concat('{"name":"2.py"',',','"type":"File"}'))),'yes','no')
    ,'no')
    ,'no')
    

    这会检查我的 blob 是否有 file1.txt、file2.txt 和 2.py

    如果是,我将是分配给变量否则否

    你也可以使用 if 条件

    【讨论】:

    • 非常感谢,感谢您的帮助!
    • 很高兴知道。 :-)
    【解决方案3】:

    你可以试试这个(Python)吗?

    import fnmatch
    import os
     
    rootPath = '/'
    pattern = '*.mp3'
     
    for root, dirs, files in os.walk(rootPath):
        for filename in fnmatch.filter(files, pattern):
            print( os.path.join(root, filename))
    

    【讨论】:

      猜你喜欢
      • 2018-06-19
      • 2011-10-14
      • 2017-11-02
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      相关资源
      最近更新 更多