DataWorks为您提供遍历节点(for-each节点),您可以通过for-each节点来循环遍历赋值节点传递的结果集。同时您也可以重新编排for-each节点内部的业务流程。本文为您介绍for-each节点的组成与应用逻辑。

应用场景

DataWorks的for-each节点主要用于有循环遍历的场景,且需要与赋值节点联合使用,将赋值节点作为for-each节点的上游节点,将赋值节点的输出结果赋值给for-each节点后,一次次循环来遍历赋值节点的输出结果。
for-each使用for-each节点时,使用限制与注意事项请参见下文的使用限制与注意事项
此外,for-each节点也是拥有内部节点的节点,内部节点可用来编译循环遍历的任务代码,详情请参见下文的节点组成

使用限制与注意事项

  • 上下游依赖

    for-each遍历节点需要遍历赋值节点传递的值,所以赋值节点需作为for-each节点的上游节点,for-each节点需要依赖赋值节点。

  • 循环支持
    • 仅DataWorks标准版及以上版本支持使用for-each节点。
    • for-each节点最多支持循环128次,如果超过了128次,则运行会报错。实际循环遍历次数由上游赋值节点实际输出控制。
      • 一维数组类型的输出,循环遍历次数即为一维数组元素的个数。

        例如,赋值节点的赋值语言为SEHLL或Python(Python2)时,输出结果为一维数组:2021-03-28,2021-03-29,2021-03-30,2021-03-31,2021-04-01,则for-each节点会循环5次完成遍历。

      • 二维数组类型的输出,循环遍历次数即为二维数组元素的行数。
        例如,赋值节点的赋值语言为OdpsSQL时,输出结果为二维数组:
        +----------------------------------------------+
        | uid            | region | age_range | zodiac |
        +----------------------------------------------+
        | 0016359810821  | 湖北省 | 30~40岁   | 巨蟹座 |
        | 0016359814159  | 未知   | 30~40岁   | 巨蟹座 |
        +----------------------------------------------+
        则for-each节点会循环2次完成遍历。
  • 内部节点
    • 您可以删除for-each节点的内部节点间的依赖关系,重新编排内部业务流程,但需要分别将start节点end节点分别作为for-each节点内部业务流程的首末节点。
    • 在for-each节点的内部节点使用分支节点进行逻辑判断或者结果遍历时,需要同时使用归并节点。
  • 调测运行
    • DataWorks为标准模式时,不支持在DataStudio界面直接测试运行for-each节点。

      如果您想测试验证for-each节点的运行结果,您需要将包含for-each节点的任务发布提交到运维中心,在运维中心页面运行for-each节点任务。

    • 在运维中心查看for-each节点的执行日志时,您需要右键实例,单击查看内部节点来查看内部节点的执行日志。

节点组成

DataWorks的for-each节点是包含内部节点的一种特殊节点,您在创建完成for-each节点时,同时也自动创建完成了三个内部节点:start节点(循环开始节点)、sql节点(循环任务节点)、end节点(循环结束判断节点),通过内部节点组织成内部节点流程,实现对上游赋值接节点输出结果的循环遍历。for-each内部节点如上图所示:
  • sql节点
    DataWorks默认为您创建好了一个SQL类型的内部任务运行节点,您也可以删除默认的sql节点后,自定义内部循环遍历任务的运行节点。
    • 您的循环遍历任务是SQL类型的任务,则可以直接双击默认的sql节点,进入节点的代码开发页面开发任务代码。
    • 您的循环遍历任务比较复杂,您可以在内部节点流程中新建其他任务节点,并根据实际情况重新构建节点的运行流程。
      说明 自定义循环任务节点时,您可以删除内部节点间的依赖关系,重新编排循环节点内部业务流程,但需要分别将start节点end节点分别作为for-each节点内部业务流程的首末节点。
  • start节点end节点
    是内部节点业务流程每次循环遍历的开始节点与结束节点,不承载具体的任务代码。
    说明 for-each节点的end节点不控制循环遍历的次数,for-each节点的循环遍历次数由上游赋值节点实际输出控制。

内置变量

DataWorks的for-each节点每次循环遍历赋值节点的输出结果时,您可以通过一些内置的变量来获取当前已循环次数和偏移量。
内置变量 含义 与for循环对比
${dag.loopDataArray} 获取赋值节点的数据集 相当于for循环中的代码结果:
data=[]
${dag.foreach.current} 获取当前遍历值 以下面的for循环代码为例:
for(int i=0;i<data.length;i++) {
   print(data[i]);
}
  • data[i]相当于${dag.foreach.current}
  • i相当于${dag.offset}
${dag.offset} 当前偏移量(每一次遍历相对于第一次的偏移量)
${dag.loopTimes} 获取当前遍历次数 -
在您了解自己输出的表结构的情况下,您可以使用如下变量方式,获取其他变量取值。
其他变量 含义
${dag.foreach.current[n]} 上游赋值节点的输出结果为二维数组时,每次遍历时获取当前数据行的某列的数据。
${dag.loopDataArray[i][j]} 上游赋值节点的输出结果为二维数组时,获取数据集中具体i行j列的数据。
${dag.foreach.current[n]} 上游赋值节点的输出结果为一维数组时,获取具体某列数据。

内置变量取值案例

  • 案例1
    上游赋值节点为shell节点,最后一条输出结果为2021-03-28,2021-03-29,2021-03-30,2021-03-31,2021-04-01,此时,各变量的取值如下:
    说明 由于输出结果为一维数组,数组元素个数为5(逗号分隔每个元素),因此for-each总遍历次数为5。
    内置变量 第1次循环遍历的取值 第2次循环遍历的取值
    ${dag.loopDataArray} 2021-03-28,2021-03-29,2021-03-30,2021-03-31,2021-04-01
    ${dag.foreach.current} 2021-03-28 2021-03-29
    ${dag.offset} 0 1
    ${dag.loopTimes} 1 2
    ${dag.foreach.current[3]} 2021-03-30
  • 案例2
    上游赋值节点为ODPS SQL节点,最后一条select语句查询出两条数据:
    +----------------------------------------------+
    | uid            | region | age_range | zodiac |
    +----------------------------------------------+
    | 0016359810821  | 湖北省 | 30~40岁   | 巨蟹座 |
    | 0016359814159  | 未知   | 30~40岁   | 巨蟹座 |
    +----------------------------------------------+
    此时,各变量的取值如下:
    说明 由于输出结果为二维数组,数组行数为2,因此for-each总遍历次数为2。
    内置变量 第1次循环遍历的取值 第2次循环遍历的取值
    ${dag.loopDataArray}
    +----------------------------------------------+
    | uid            | region | age_range | zodiac |
    +----------------------------------------------+
    | 0016359810821  | 湖北省 | 30~40岁   | 巨蟹座 |
    | 0016359814159  | 未知   | 30~40岁   | 巨蟹座 |
    +----------------------------------------------+
    ${dag.foreach.current} 0016359810821,湖北省,30~40岁,巨蟹座 0016359814159,未知,30~40岁,巨蟹座
    ${dag.offset} 0 1
    ${dag.loopTimes} 1 2
    ${dag.foreach.current[0]} 0016359810821 0016359814159
    ${dag.loopDataArray[1][0]} 0016359814159