【问题标题】:FLATTEN On bag NOT working as expectedFLATTEN 在袋子上没有按预期工作
【发布时间】:2015-06-01 02:25:24
【问题描述】:

输入:一个包含地图数据的.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 中压平袋子的任何输入。

【问题讨论】:

    标签: apache-pig flatten bag


    【解决方案1】:

    这里的问题是当你没有为map指定架构时,它默认为bytearray,你可以在official documentation中看到:

    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,因此它不会获得默认值,即bytearray

    A = LOAD 'a.csv' AS (bank_details:bag{t:(bank_name:chararray)});
    

    编辑

    抱歉,我没有看到在第二种情况下您没有使用map,而是直接使用bag。如果你想使用map,你可以只要你指出架构来避免上面提到的:

    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)
    

    【讨论】:

    • 同意你的想法,在我的用例中,我有一张地图,其中的值是不同的数据类型。它不是具有所有袋子值的地图。任何关于显式转换的输入,就像我尝试别名 C 的方式一样:C = FOREACH A GENERATE bank_details#'banks' AS银行:bag{t:(bank:chararray)};
    • @MuraliRao 我不确定我理解你的意思......你有一张不同类型的地图,对吧?您不能进行从 bytearraybag 的显式转换,这两个类没有任何共同点,因此您会遇到异常。解决此问题的唯一方法是为地图指定架构。如果值可能会有所不同,你不能把它们都放在一个袋子里吗?我的意思是,里面有袋子的地图:A = LOAD 'a.csv' AS (bank_details:map[bag{t:(name:chararray)}]);
    • 是的,我的意思是地图具有不同数据类型的值。例如。 key1#2, key2#{(bofa),(chase)}。我知道我们将无法将字节数组转换为包。将尝试将所有键值作为包。感谢您的投入!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多