FLATTEN On bag 未按预期工作
FLATTEN On bag NOT working as expected
输入: a.csv 具有地图数据的文件
[banks#{(bofa),(chase)}]
猪脚本:
A = LOAD 'a.csv' AS (bank_details:map[]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
输出:B:
({(bofa),(chase)})
在袋子上应用 Flatten
C = FOREACH A GENERATE bank_details#'banks' AS banks: bag{t:(bank:chararray)};
D = FOREACH C GENERATE FLATTEN(banks);
输出:D:
org.apache.pig.backend.executionengine.ExecException: ERROR 0: Exception while executing [POProject (Name: Project[bag][0] - scope-114 Operator Key: scope-114) children: null at []]: java.lang.ClassCastException: org.apache.pig.data.DataByteArray cannot be cast to org.apache.pig.data.DataBag
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.PhysicalOperator.getNext(PhysicalOperator.java:366)
预期输出:
(bofa)
(chase)
如果输入文件有如下包:
输入:a.csv
{(bofa),(chase)}
猪脚本:
A = LOAD 'a.csv' AS (bank_details:bag{t:(bank_name:chararray)});
B = FOREACH A GENERATE FLATTEN(bank_details) AS bank_name;
输出:B:生成扁平化结果
(bofa)
(chase)
关于为什么我们无法将别名 C 和 D 中的袋子压平的任何意见。
这里的问题是,当您没有为 map
指定模式时,它默认为 bytearray
,正如您在 official documentation:[=30= 中看到的那样]
A = LOAD 'a.csv' AS (bank_details:map[]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
describe B;
B: {bank_name: bytearray}
因此,当您尝试将其转换为 bag
时,结果将是 ClassCastException
,因为 DataByteArray
无法转换为 DataBag
。如果你在 C
上执行 dump
它仍然有效,因为你没有对数据进行任何实际操作,只是投影它。但是,一旦您调用 FLATTEN
函数,它就会收到一个 DataBag
,并在尝试将您的 bytearray
转换为它时失败。
它在你的第二种情况下起作用的原因是你正确地指示了地图的模式,它是 bag
,所以它不会获得默认值,即 [=14] =]:
A = LOAD 'a.csv' AS (bank_details:bag{t:(bank_name:chararray)});
编辑
抱歉,我没有看到在第二种情况下你没有使用 map
,你直接使用了 bag
。如果你想使用一个map
,你只要指明schema就可以避免上面提到的:
A = LOAD 'a.csv' AS (bank_details:map[{(name:chararray)}]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
dump B;
(bofa)
(chase)
输入: a.csv 具有地图数据的文件
[banks#{(bofa),(chase)}]
猪脚本:
A = LOAD 'a.csv' AS (bank_details:map[]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
输出:B:
({(bofa),(chase)})
在袋子上应用 Flatten
C = FOREACH A GENERATE bank_details#'banks' AS banks: bag{t:(bank:chararray)};
D = FOREACH C GENERATE FLATTEN(banks);
输出:D:
org.apache.pig.backend.executionengine.ExecException: ERROR 0: Exception while executing [POProject (Name: Project[bag][0] - scope-114 Operator Key: scope-114) children: null at []]: java.lang.ClassCastException: org.apache.pig.data.DataByteArray cannot be cast to org.apache.pig.data.DataBag
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.PhysicalOperator.getNext(PhysicalOperator.java:366)
预期输出:
(bofa)
(chase)
如果输入文件有如下包:
输入:a.csv
{(bofa),(chase)}
猪脚本:
A = LOAD 'a.csv' AS (bank_details:bag{t:(bank_name:chararray)});
B = FOREACH A GENERATE FLATTEN(bank_details) AS bank_name;
输出:B:生成扁平化结果
(bofa)
(chase)
关于为什么我们无法将别名 C 和 D 中的袋子压平的任何意见。
这里的问题是,当您没有为 map
指定模式时,它默认为 bytearray
,正如您在 official documentation:[=30= 中看到的那样]
A = LOAD 'a.csv' AS (bank_details:map[]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
describe B;
B: {bank_name: bytearray}
因此,当您尝试将其转换为 bag
时,结果将是 ClassCastException
,因为 DataByteArray
无法转换为 DataBag
。如果你在 C
上执行 dump
它仍然有效,因为你没有对数据进行任何实际操作,只是投影它。但是,一旦您调用 FLATTEN
函数,它就会收到一个 DataBag
,并在尝试将您的 bytearray
转换为它时失败。
它在你的第二种情况下起作用的原因是你正确地指示了地图的模式,它是 bag
,所以它不会获得默认值,即 [=14] =]:
A = LOAD 'a.csv' AS (bank_details:bag{t:(bank_name:chararray)});
编辑
抱歉,我没有看到在第二种情况下你没有使用 map
,你直接使用了 bag
。如果你想使用一个map
,你只要指明schema就可以避免上面提到的:
A = LOAD 'a.csv' AS (bank_details:map[{(name:chararray)}]);
B = FOREACH A GENERATE FLATTEN(bank_details#'banks') AS bank_name;
dump B;
(bofa)
(chase)