如何从 Java 中的 Avro-Parquet 文件中读取特定字段?

How to read specific fields from Avro-Parquet file in Java?

如何从 java 中的 avro-parquet 文件读取部分字段?

我想我可以定义一个 avro 模式,它是存储记录的一个子集,然后读取它们...但是我得到一个异常。

这是我尝试解决的方法

我有 2 个 avro 模式:

ClassB 的字段是 ClassA 的子集。

        final Builder<ClassB> builder = AvroParquetReader.builder(files[0].getPath());
        final ParquetReader<ClassB> reader = builder.build();
        //AvroParquetReader<ClassA> readerA = new AvroParquetReader<ClassA>(files[0].getPath());
        ClassB record = null;
        final List<ClassB> list = new ArrayList<>();
        while ((record = reader.read()) != null) {
            list.add(record);
        }

但是我在 (record=reader.read()) 线上收到 ClassCastExceptionCannot convert ClassA to ClassB

我想 reader 正在从文件中读取模式。

我尝试发送模型(即 builder.withModel),但由于 classB extends org.apache.avro.specific.SpecificRecordBase 它抛出异常。

我尝试在配置中设置架构并通过 builder.withConfig 设置它,但没有雪茄...

所以...

两件事:

  • AvroReadSupport.setRequestedProjection(hadoopConf, ClassB.$Schema) 可用于为所选列设置投影。
  • reader.readNext 方法仍然会 return 一个 ClassA 对象,但会清除 ClassB.
  • 中不存在的字段

要直接使用 reader,您可以执行以下操作:

AvroReadSupport.setRequestedProjection(hadoopConf, ClassB.SCHEMA$);
final Builder<ClassB> builder = AvroParquetReader.builder(files[0].getPath());
final ParquetReader<ClassA> reader = builder.withConf(hadoopConf).build();

ClassA record = null;
final List<ClassA> list = new ArrayList<>();
while ((record = reader.read()) != null) {
    list.add(record);
}

此外,如果您打算使用输入格式来读取 avro-parquet 文件,还有一个方便的方法 - 这里是一个 spark 示例:

        final Job job = Job.getInstance(hadoopConf);
        ParquetInputFormat.setInputPaths(job, pathGlob);
        AvroParquetInputFormat.setRequestedProjection(job, ClassB.SCHEMA$);

        @SuppressWarnings("unchecked")
        final JavaPairRDD<Void, ClassA> rdd = sc.newAPIHadoopRDD(job.getConfiguration(), AvroParquetInputFormat.class,
                Void.class, ClassA.class);