gpt4 book ai didi

java - 用于将字段从原语演变为联合的 Avro 模式解析

转载 作者:搜寻专家 更新时间:2023-11-01 02:50:35 24 4
gpt4 key购买 nike

我正在使用 Avro 1.7.0 使用它的 Java's generic representation API我在处理我们当前的模式演变案例时遇到了问题。我们在这里处理的场景是通过将字段更改为 null 的联合来使原始类型字段成为可选字段。和那个原始类型。

我将使用一个简单的例子。基本上,我们的模式是:

  • Initial:一条记录​​,带有一个类型为 int 的字段
  • 第二个版本:相同的记录,相同的字段名称,但类型现在是 null 的并集和 int

根据schema resolution chapter根据 Avro 的规范,这种情况的解决方案应该是:

if reader's is a union, but writer's is not
The first schema in the reader's union that matches the writer's schema is recursively resolved against it. If none match, an error is signalled.

我的解释是我们应该将使用初始模式序列化的数据正确解析为 int是读者模式中联合的一部分。

但是,当运行使用版本 2 回读版本 1 序列化记录的测试时,我得到

org.apache.avro.AvroTypeException: Attempt to process a int when a union was expected.

下面的测试正好说明了这一点:

@Test
public void testReadingUnionFromValueWrittenAsPrimitive() throws Exception {
Schema writerSchema = new Schema.Parser().parse("{\n" +
" \"type\":\"record\",\n" +
" \"name\":\"NeighborComparisons\",\n" +
" \"fields\": [\n" +
" {\"name\": \"test\",\n" +
" \"type\": \"int\" }]} ");

Schema readersSchema = new Schema.Parser().parse(" {\n" +
" \"type\":\"record\",\n" +
" \"name\":\"NeighborComparisons\",\n" +
" \"fields\": [ {\n" +
" \"name\": \"test\",\n" +
" \"type\": [\"null\", \"int\"],\n" +
" \"default\": null } ] }");

// Writing a record using the initial schema with the
// test field defined as an int
GenericData.Record record = new GenericData.Record(writerSchema);
record.put("test", Integer.valueOf(10));
ByteArrayOutputStream output = new ByteArrayOutputStream();
JsonEncoder jsonEncoder = EncoderFactory.get().
jsonEncoder(writerSchema, output);
GenericDatumWriter<GenericData.Record> writer = new
GenericDatumWriter<GenericData.Record>(writerSchema);
writer.write(record, jsonEncoder);
jsonEncoder.flush();
output.flush();

System.out.println(output.toString());

// We try reading it back using the second schema
// version where the test field is defined as a union of null and int
JsonDecoder jsonDecoder = DecoderFactory.get().
jsonDecoder(readersSchema, output.toString());
GenericDatumReader<GenericData.Record> reader =
new GenericDatumReader<GenericData.Record>(writerSchema,
readersSchema);
GenericData.Record read = reader.read(null, jsonDecoder);

// We should be able to assert that the value is 10 but it
// fails on reading the record before getting here
assertEquals(10, read.get("test"));
}

我想知道我的期望是否正确(这应该会成功解决,对吧?)或者我在哪些地方没有正确使用 avro 来处理这种情况。

最佳答案

将原始模式迁移到 null 和原始的联合的期望是正确的。

上面代码的问题在于解码器的创建方式。解码器需要作者的模式而不是读者的模式。

而不是这样做:

JsonDecoder jsonDecoder = DecoderFactory.get().
jsonDecoder(readersSchema, output.toString());

应该是这样的:

JsonDecoder jsonDecoder = DecoderFactory.get().
jsonDecoder(writerSchema, output.toString());

感谢 Doug Cutting 在 avro 的用户邮件列表中的回答: http://mail-archives.apache.org/mod_mbox/avro-user/201208.mbox/browser

关于java - 用于将字段从原语演变为联合的 Avro 模式解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12061765/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com