編集:私がやりたいことを一般的に説明しようとします。
入力の 1 行は次のようになります: field1、field2、textfield
現在、テキストフィールドは固定文字数の文字列エントリです。この文字列を解析して、これらの文字から部分文字列を抽出したいと考えています。たとえば、最初の 10 文字を抽出してフィールドにし、次の 15 文字を抽出してフィールドにするなど...
その部分は問題ありません。問題は、各行に同じテキストフィールド ルールが含まれていないことです。基本的に、 field1とfield2は、そのテキスト フィールドを解析するために使用するキーを表します。マップ内のこのキーは、(出力で使用するために) 抽出しているすべてのフィールド名の配列と、文字列内の各フィールドの長さ (解析できるようにするため) を指します。
私が抱えている問題は、各出力が異なるフィールドと値を持つバッグになることです。10 個のタプルを持つバッグを持つ行もあれば、5 または 6 を持つバッグを持つ行もあります。exec 関数でスキーマを定義する方法が必要です。
編集:
私の主な目標は、UDF 入力パラメーターを使用してルックアップ マップを使用し、出力スキーマを導出できるようにすることです。投稿の残りの部分は参照としてここに残しますが、私の主な目標は、入力パラメーターを使用してマップにアクセスし、フィールド タイプの配列を取得できるかどうかを学習または確認することです。
それぞれがエイリアスまたはキーを持つタプルのバッグを返そうとしています。タプルのエイリアスとして使用する必要がある文字列の配列を含むマップがあります。UDF へのユーザー入力に基づいて、スキーマを含む正しい配列をフェッチします。
ユーザーの入力があるため、これは私の実行機能で正常に機能しています。しかし、その入力を出力スキーマにも利用する方法がわかりません。
UDF 入力の場合、最初のパラメーターと 2 番目のパラメーターを組み合わせたものが、配列を取得するためのキーになります。3 番目のパラメーターは、配列ごとに異なる特定の文字間隔で解析する必要がある大きなテキスト フィールドです。
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);
}
}
**ここでは、入力に使用するスキーマを決定するために、ユーザーの入力に基づいて以下の配列にアクセスする方法が必要です。ここにジャンクをハードコーディングしました。しかし、私の 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});
}
}
実際には、10 個以上の配列があり、入力によってどの配列とどのスキーマを使用するかが決まります。私はしばらくこれにこだわっていますが、何をしようとしてもそれを得ることができないようです.