pigjavaudf:基于输入参数生成动态元组模式

pigjavaudf:基于输入参数生成动态元组模式,java,apache-pig,udf,Java,Apache Pig,Udf,编辑:我将试着大致解释一下我想做什么 1行输入看起来像:field1,field2,textfield 现在textfield是一个固定字符数的字符串条目。我想解析这个字符串以从这些字符中提取子字符串。例如,我想提取前10个字符并将其作为字段,提取下15个字符并将其作为字段,等等 那部分很好。问题在于并非每一行都有相同的文本字段规则。基本上,field1和field2将代表我用来解析该文本字段的键。映射中的这个键将指向我正在提取的所有字段名(用于输出)的数组,以及字符串中每个字段的长度(以便我可

编辑:我将试着大致解释一下我想做什么

1行输入看起来像:field1,field2,textfield

现在textfield是一个固定字符数的字符串条目。我想解析这个字符串以从这些字符中提取子字符串。例如,我想提取前10个字符并将其作为字段,提取下15个字符并将其作为字段,等等

那部分很好。问题在于并非每一行都有相同的文本字段规则。基本上,field1field2将代表我用来解析该文本字段的键。映射中的这个键将指向我正在提取的所有字段名(用于输出)的数组,以及字符串中每个字段的长度(以便我可以解析)

我的问题是,我的每个输出都将是一个包,其中包含不同的字段和值。有些行可能有10个元组的包,其他行可能有5或6个元组。我需要一种在exec函数中定义模式的方法

编辑:

我的主要目标是能够使用我的UDF输入参数来使用查找映射来派生我的输出模式。我将把这篇文章的其余部分留作参考,但我的主要目标是学习或找出是否可以使用输入参数访问映射来检索字段类型的数组

我试图返回一包元组,每个元组都有别名或键。我有一个映射,其中包含一个字符串数组,需要用作元组的别名。根据用户对UDF的输入,我将获取包含我的模式的正确数组

这在我的exec函数中工作正常,因为我有用户的输入。但我不知道如何将输入也用于输出模式

对于UDF输入,第一个参数与第二个参数组合将是获取数组的键。第三个参数是一个大的文本字段,我需要以特定的字符间隔对其进行解析,每个数组的解析都不同

public class BagTupleExampleUDF extends EvalFunc<DataBag> {

TupleFactory mTupleFactory = TupleFactory.getInstance();
BagFactory mBagFactory = BagFactory.getInstance();

/* Set up the number of fields for each loop/segment type */
HashMap<String, String[]> FieldsMap = new HashMap<String, String[]>();
Map<String,int[]> FieldsNumChar = new HashMap<String, int[]>();


@Override
public DataBag exec(Tuple tuple) throws IOException {
    setUpMaps();


    // expect one string
    if (tuple == null || tuple.size() != 3) {
        throw new IllegalArgumentException("BagTupleExampleUDF: requires 3 input parameters.");
    }
    try {

         String param1 = (String)tuple.get(0);
         String param2 = (String)tuple.get(1);
         String textArea = (String)tuple.get(2);

         String processingText = textArea;



         String paramsCombined = loop.trim()+segment.trim();
         String[] fieldsArray = loopSegmentFieldsMap.get(paramsCombined);

         int[] endFieldsIndex = loopSegmentFieldsNumChar.get(paramsCombined);
         DataBag output = mBagFactory.newDefaultBag();

         Tuple outputTuple = mTupleFactory.newTuple();
         for(int i = 0; i < fieldsArray.length; i++){

                String temp = processingText.substring(0,endFieldsIndex[i]);
                processingText = processingText.substring(endFieldsIndex[i]);
             outputTuple.append(temp);

         }




        output.add(outputTuple);


        return output;
    }
    catch (Exception e) {
        throw new IOException("BagTupleExampleUDF: caught exception processing input.", e);
    }
}
公共类BagTupleExampleUDF扩展了EvalFunc{
TupleFactory mTupleFactory=TupleFactory.getInstance();
BagFactory mBagFactory=BagFactory.getInstance();
/*设置每个循环/段类型的字段数*/
HashMap FieldsMap=新HashMap();
Map FieldsNumChar=new HashMap();
@凌驾
公共数据库执行器(Tuple-Tuple)引发IOException{
setUpMaps();
//期望一个字符串
if(tuple==null | | tuple.size()!=3){
抛出新的IllegalArgumentException(“BagTupleExampleUDF:需要3个输入参数”);
}
试一试{
String param1=(String)tuple.get(0);
stringparam2=(String)tuple.get(1);
stringtextarea=(String)tuple.get(2);
字符串处理文本=文本区域;
字符串参数组合=loop.trim()+segment.trim();
String[]fieldsArray=loopSegmentFieldsMap.get(paramsCombined);
int[]endFieldsIndex=loopSegmentFieldsNumChar.get(参数组合);
数据包输出=mBagFactory.newDefaultBag();
Tuple outputTuple=mTupleFactory.newTuple();
for(int i=0;i
**在这里,我需要一些方法来根据用户的输入访问下面的数组,以确定使用哪个架构来填充。我现在在这里硬编码了垃圾。但是在for循环中,我需要正确的array.length,然后当我设置字段架构时,我将使用array[I]

但我无法在此函数中访问数组**

public Schema outputSchema(Schema input) {
        setUpMaps();
        // Function returns a bag with this schema: { (Double), (Double) }
        // Thus the outputSchema type should be a Bag containing a Double
        try{

            Schema tupleSchema = new Schema();
            String[] test = FieldsMap.get("array1");
            for(int i = 0; i<test.length; i++){
                tupleSchema.add(new Schema.FieldSchema(test[i], DataType.CHARARRAY));

            }


            return new Schema(new Schema.FieldSchema(getSchemaName(this.getClass().getName().toLowerCase(), input), tupleSchema, DataType.BAG));
            }
        catch (Exception e){
            throw new RuntimeException(e);
        }
    }



        public void setUpMaps(){
            FieldsMap.put("array1", new String[]{"alias1","alias2","alias3","alias4","alias5","alias6","alias7","alias8","alias9"});

            FieldsNumChar.put("array1",new int[] {6,9,4,4,30,2,5,4,11});

        }
    }
公共模式输出模式(模式输入){
setUpMaps();
//函数返回具有以下架构的包:{(Double),(Double)}
//因此,outputSchema类型应该是一个包含双精度
试一试{
Schema tupleSchema=新模式();
String[]test=FieldsMap.get(“array1”);

对于(int i=0;iI)我不太明白您在这里要做什么,但AFAIK outputSchema()只在前端调用。因此,在后端实际执行时,您的映射将不可用。如果您需要后端前端调用中的某些内容,可以使用UDFContext()是的,我确实看过。不幸的是,我需要的是一种从后端到前端发送东西的方法,从我所看到的情况来看,这似乎是不可能的。我一直在尝试使用OutputSchema的不同路线,但我无法想出如何在没有它的情况下返回包。我添加了一些更多的信息这有助于解释这一点吗?好吧,我想我现在知道你想做什么了。但我认为这是不可能的,因为就我所知,模式必须在调用前端后修复,我认为你正在尝试根据输入动态生成。是的,这也是我的理解l、 因此,我最终要做的是从exec函数返回一个映射,它允许我动态链接我的键和值对。因此,现在我的每一行都有一个包含解析字段的映射。然后,当我分组行时,我有另一个结合映射的UDF。这并不是我所希望的,因为我真的想要一个使映射对能够在行中显示值并定义其模式的方法,但我认为我应该能够处理这个问题。