如何从文本文件生成模式? (Hadoop的猪)

时间:2013-08-12 09:12:55

标签: apache-pig

不知何故,我得到了filename.log,例如(分隔标签)

Name:Peter Age:18

Name:Tom Age:25

Name:Jason Age:35

因为key列的值可能不同我加载文本时无法定义架构,如

a = load 'filename.log' as (Name:chararray,Age:int);

我也不想像

那样按位置调用
b = foreach a generate $0,$1;

我想要做的是,仅从filename.log开始,可以通过键调用每个值,例如

a = load 'filename.log' using PigStorage('\t');

b = group b by Name;

c = foreach b generate group, COUNT(b);

dump c;

为此目的,我写了一些Java UDF,它分隔键:值并获取元组中每个字段的值,如下所示

public class SPLITALLGETCOL2 extends EvalFunc<Tuple>{
    @Override
    public Tuple exec(Tuple input){
        TupleFactory mTupleFactory = TupleFactory.getInstance();
        ArrayList<String> mProtoTuple = new ArrayList<String>();
        Tuple output;
        String target=input.toString().substring(1, input.toString().length()-1);
        String[] tokenized=target.split(",");
        try{
            for(int i=0;i<tokenized.length;i++){
                mProtoTuple.add(tokenized[i].split(":")[1]);
            }
            output =  mTupleFactory.newTupleNoCopy(mProtoTuple);
            return output;
        }catch(Exception e){
            output =  mTupleFactory.newTupleNoCopy(mProtoTuple);
            return output;
        }
    }
}

我应该如何改变这种方法来获得我想要的东西?或者我应该如何编写其他UDF才能到达那里?

1 个答案:

答案 0 :(得分:0)

无论你做什么,都不要使用元组来存储输出。元组用于存储固定数量的字段,您可以在其中了解每个字段包含的内容。由于您不知道密钥将在Name,Age表单中(或者甚至存在,或者不会有更多),因此您应该使用bag。包是无序的元组。只要元组具有相同的模式,它们就可以包含任意数量的元组。这些都是架构B: {T:(key:chararray, value:chararray)}的有效行李:

{(Name,Foo),(Age,Bar)}
{(Age,25),(Name,Jim)}
{(Name,Bob)}
{(Age,30),(Name,Roger),(Hair Color,Brown)}
{(Hair Color,),(Name,Victor)} -- Note the Null value for Hair Color

然而,听起来你真的想要一张地图:

<强> myudf.py

@outputSchema('M:map[]')
def mapize(the_input):
    out = {}
    for kv in the_input.split(' '):
        k, v = kv.split(':')
        out[k] = v
    return out

<强> myscript.pig

register '../myudf.py' using jython as myudf ;

A = LOAD 'filename.log' AS (total:chararray) ; 
B = FOREACH A GENERATE myudf.mapize(total) ;

-- Sample usage, grouping by the name key.
C = GROUP B BY M#'Name' ;

使用#运算符,您可以使用您提供的密钥从地图中提取所有值。您可以阅读有关地图here的更多信息。