5

嗨,正在寻找 API 来使用我拥有的 Pojos 编写 parquest。我能够使用反射生成 avro 架构,然后使用 AvroSchemaConverter 创建镶木地板架构。此外,我无法找到将 Pojos 转换为 GenericRecords (avro) 的方法,否则我本可以使用 AvroParquetWriter 将 Pojos 写入镶木地板文件。有什么建议么 ?

4

3 回答 3

1

如果你想通过 avro 你有两个选择:

1) 让 avro 生成您的 pojos(请参阅此处的教程)。生成的 pojo 扩展了 SpecificRecord,然后可以与 AvroParquetWriter 一起使用。

2) 自己编写从 pojo 到 GenericRecord 的转换。您可以手动执行此操作,或者更通用的解决方案是使用反射。但是,当我尝试读取数据时,我遇到了这种方法的困难。根据提供的模式,avro 在类路径中找到了 pojo,并尝试实例化一个 SpecificRecord 而不是 GenericRecord。由于这个原因,我选择了选项 1。

Parquet 现在也支持直接写 pojo。是 parquet github 页面上的拉取请求。但是,我认为这还不是正式版本的一部分。换句话说,我没有在 maven 中找到这段代码。

于 2014-10-24T21:39:25.240 回答
0

免责声明:以下代码是我赶时间时编写的。它效率不高,未来版本的镶木地板肯定会更直接地解决这个问题。话虽如此,这是一种轻量级的低效方法,可以满足您的需求。策略是 POJO -> AVRO -> PARQUET

  1. POJO -> AVRO:通过反射声明一个模式。根据模式声明作者和读者。在转换时将对象写入字节流并将其作为 avro 读回。
  2. AVRO -> Parquet:使用 parquet-me 项目中包含的 AvroParquetWriter。

private static final Schema avroSchema = ReflectData.AllowNull.get().getSchema(YOURCLASS.class);
private static final ReflectDatumWriter<YOURCLASS> reflectDatumWriter = new ReflectDatumWriter<>(avroSchema);
private static final GenericDatumReader<Object> genericRecordReader = new GenericDatumReader<>(avroSchema);

public GenericRecord toAvroGenericRecord() throws IOException {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    reflectDatumWriter.write(this, EncoderFactory.get().directBinaryEncoder(bytes, null));
    return (GenericRecord) genericRecordReader.read(null, DecoderFactory.get().binaryDecoder(bytes.toByteArray(), null));
}

还有一件事:parquet writers 目前似乎对空字段非常严格。在尝试写入镶木地板之前,请确保您的所有字段都不为空

于 2015-03-27T04:13:22.527 回答
0

我无法找到现有的解决方案,所以我自己实现了它。这是实现的链接:https ://gist.github.com/alexeygrigorev/eab72e40c6051e0163a6693054906d66

简而言之,它执行以下操作:

  • 使用反射从 pojo 中获取 Avro 模式
  • 使用模式和反射将 pojos 转换为GenericRecord对象
  • 如果 pojo 包含其他 pojo 或 pojo 列表,则递归应用反射
于 2018-01-17T13:49:27.687 回答