猪铸造/数据类型

Posted

技术标签:

【中文标题】猪铸造/数据类型【英文标题】:Pig casting / datatypes 【发布时间】:2016-01-11 17:04:32 【问题描述】:

我正在尝试将关系转储到 AVRO 文件中,但出现了一个奇怪的错误:

org.apache.pig.data.DataByteArray cannot be cast to java.lang.CharSequence

我不使用DataByteArray(字节数组),请参阅下面的关系描述。

sensitiveSet: rank_ID: long,name: chararray,customerId: long,VIN: chararray,birth_date: chararray,fuel_mileage: chararray,fuel_consumption: chararray

即使我进行显式转换,我也会遇到同样的错误:

sensitiveSet = foreach sensitiveSet generate (long) $0, (chararray) $1, (long) $2, (chararray) $3, (chararray) $4, (chararray) $5, (chararray) $6;

STORE sensitiveSet INTO 'testOut2222.avro'
USING org.apache.pig.piggybank.storage.avro.AvroStorage('no_schema_check', 'schema', '"type":"record","name":"xxxx","namespace":"","fields":["name":"rank_ID","type":"long","name":"name","type":"string","store":"no","sensitive":"na","name":"customerId","type":"string","store":"yes","sensitive":"yes","name":"VIN","type":"string","store":"yes","sensitive":"yes","name":"birth_date","type":"string","store":"yes","sensitive":"no","name":"fuel_mileage","type":"string","store":"yes","sensitive":"no","name":"fuel_consumption","type":"string","store":"yes","sensitive":"no"]');

已编辑:

我正在尝试定义一个输出模式,它应该是一个包含另外两个元组的元组,即stats:tuple(c:tuple(),d:tuple)

下面的代码没有按预期工作。它以某种方式产生结构:

stats:tuple(b:tuple(c:tuple(),d:tuple()))

下面是describe产生的输出。

sourceData: com.mortardata.pig.dataspliter_36: (stats: ((name: chararray,customerId: chararray,VIN: chararray,birth_date: chararray,fuel_mileage: chararray,fuel_consumption: chararray),(name: chararray,customerId: chararray,VIN: chararray,birth_date: chararray,fuel_mileage: chararray,fuel_consumption: chararray)))

是否可以创建如下结构,这意味着我需要从上一个示例中删除元组 b。

grunt> describe sourceData;
sourceData: t: (s: (name: chararray,customerId: chararray,VIN: chararray,birth_date: chararray,fuel_mileage: chararray,fuel_consumption: chararray),n: (name: chararray,customerId: chararray,VIN: chararray,birth_date: chararray,fuel_mileage: chararray,fuel_consumption: chararray))

下面的代码没有按预期工作。

  public Schema outputSchema(Schema input) 
    Schema sensTuple = new Schema();
    sensTuple.add(new Schema.FieldSchema("name", DataType.CHARARRAY));
    sensTuple.add(new Schema.FieldSchema("customerId", DataType.CHARARRAY));
    sensTuple.add(new Schema.FieldSchema("VIN", DataType.CHARARRAY));
    sensTuple.add(new Schema.FieldSchema("birth_date", DataType.CHARARRAY));
    sensTuple.add(new Schema.FieldSchema("fuel_mileage", DataType.CHARARRAY));
    sensTuple.add(new Schema.FieldSchema("fuel_consumption", DataType.CHARARRAY));

    Schema nonSensTuple = new Schema();
    nonSensTuple.add(new Schema.FieldSchema("name", DataType.CHARARRAY));
    nonSensTuple.add(new Schema.FieldSchema("customerId", DataType.CHARARRAY));
    nonSensTuple.add(new Schema.FieldSchema("VIN", DataType.CHARARRAY));
    nonSensTuple.add(new Schema.FieldSchema("birth_date", DataType.CHARARRAY));
    nonSensTuple.add(new Schema.FieldSchema("fuel_mileage", DataType.CHARARRAY));
    nonSensTuple.add(new Schema.FieldSchema("fuel_consumption", DataType.CHARARRAY));


    Schema parentTuple = new Schema();
    parentTuple.add(new Schema.FieldSchema(null, sensTuple, DataType.TUPLE));
    parentTuple.add(new Schema.FieldSchema(null, nonSensTuple, DataType.TUPLE));


    Schema outputSchema = new Schema();
    outputSchema.add(new Schema.FieldSchema("stats", parentTuple, DataType.TUPLE));

    return new Schema(new Schema.FieldSchema(getSchemaName(this.getClass().getName().toLowerCase(), input), outputSchema, DataType.TUPLE));

UDF 的 exec 方法返回:

public Tuple exec(Tuple tuple) throws IOException     
  Tuple parentTuple  = mTupleFactory.newTuple();
  parentTuple.append(tuple1);
  parentTuple.append(tuple2);

EDIT2(固定)

...
Schema outputSchema = new Schema();
outputSchema.add(new Schema.FieldSchema("stats", parentTuple, DataType.TUPLE));
return new Schema(new Schema.FieldSchema(getSchemaName(this.getClass().getName().toLowerCase(), input), outputSchema, DataType.TUPLE);
return outputSchema;

现在我从 UDF 返回正确的模式,其中所有项目都是 chararray 但是当我尝试将这些项目作为 type: string 存储到 avro 文件中时,我得到了同样的错误:

java.lang.Exception: org.apache.avro.file.DataFileWriter$AppendWriteException: java.lang.ClassCastException: org.apache.pig.data.DataByteArray cannot be cast to java.lang.CharSequence
        at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
        at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522)

已解决: 好的,问题是数据没有转换为 UDF 主体内的正确类型 - exec () 方法。看起来它现在可以工作了!

【问题讨论】:

你试过只使用USING ...AvroStorage()...AvroStorage('no_schema_check') 吗? 你可以看到“no_chema_check”在那里。 @heap: customerId 是 long 类型,在 avro 中它被保存为字符串,不应该是 long 类型吗? @Murali 在第一个示例中它很长,在第二个示例中,我将所有内容都转换为字符串。 您在存储之前是否使用过其他 UDF?有时 UDF 不保留架构,结果类型为 DataByteArray。此外,有时 UDF 可能会产生与架构实际报告的类型不同的类型(由于错误)。 【参考方案1】:

这通常意味着您使用的 UDF 没有保留架构,或者它在某个地方丢失了。我相信 DataByteArray 是不知道真实类型时的后备类型。您可能需要添加种姓来解决此问题,但更好的解决方案是修复任何 UDF 正在删除架构。

【讨论】:

这意味着我必须在我的 UDF 中定义 outputSchema 方法。我想知道如何定义一个包含另外两个元组的元组。 好的,我修复了 ouputSchema 代码,现在它返回正确的模式,但它不起作用......当我尝试将记录存储到 avro 文件时,总是出现同样的错误。 java.lang.Exception: org.apache.avro.file.DataFileWriter$AppendWriteException: java.lang.ClassCastException: org.apache.pig.data.DataByteArray 无法在 org.apache.hadoop.mapred 中转换为 java.lang.CharSequence .LocalJobRunner$Job.runTasks(LocalJobRunner.java:462) at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522) 所以我 100% 确定 UDF 返回 chararray,这不是猪虫吗? 好的,问题是数据未在 UDF 主体内转换为正确的类型 - exec() 方法。看起来它现在可以工作了!

以上是关于猪铸造/数据类型的主要内容,如果未能解决你的问题,请参考以下文章

类型铸造操作

如何检查猪 UDF 中的数据类型

C# 类型转换

类型转换猪 hcatalog

类型转换

Postgres 铸造复合材料类型