整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

4.4.5模式的解析

hadoop 花牛 8℃ 0评论

在选择的时候,读加数据的模式(reader的模式)可以不同于我们用于写入数据的模式(writer的模式)。这非常有用,因为它意味着模式演化。例如,为了便于说明,我们考虑新增一个description字段,形成一个新的模式:

{
    "type": "record",
    "name": "StringPair",
    "doc": "A pair of strings with an added field.",
    "fields":[
        {"name": "left", "type": "string"},
        {"name": "right", "type": "string"},
        {"name": "description", "type": "string","default": ""}
    ]
}

我们可以使用该模式来读取前面序列化的数据,因为我们已经为 description字段指定了一个默认值(空字符串)供Avro在读取没有定义字段的记录时使用。如果忽略default属性,在读取旧数据时会报错。

要想将默认值设为null而非空字符串,我们要用null Avro类型 的并集来定义description字段

{"name": "description", "type": ["null", "string"], "default":"null"}

读模式不同于写模式时,我们调用GenericDatumReader的构造函数,它取两个模式对象,即读取对象和写入对象,并按照以下顺序:

DatumReader<GenericRecord> reader =new GenericDatumReader<GenericRecord>(schema, newSchema);
Decoder decoder = DecoderFactory.defaultFactory().createBinaryDecoder (out.toByteArray(), null);
GenericRecord result = reader.read(null, decoder);
assertThat(result.get("left").toString(), is("L"));
assertThat(result.get("right").toStning(), is("R"));
assertThat(result.get("description").toString(), is(""));

对于元数据中存储有写入模式的数据文件,我们只需要显式指定写入模式,具体做法是向写入模式传递null:

DatumReader<GenericRecord> reader =new GenericDatumReader<GenericRecord>(null, newSchema);

不同读取模式的另外一个应用是去掉记录中的某些字段,该操作可以称为"投影"(projection)。记录中有大量字段但如果只需读取其中的一部分,这种做法非常有用。例如,可以使用这一模式只读取StringPair对象的 right字段:

{
    "type": "record",
    "name": "StringPair",
    "doc": "The right field of a pair of strings.",
    "fields":[
        {"name": "right", "type": "string"}
    ]
}

模式解析规则可以直接解决模式由一个版本演化为另一个版本时可能产生的问题,Avro规范中对所有Avro类型均有详细说明。表4-12从类型读/写(客户端和服务器端)的角度总结了记录演化规则。

表4-12•记录的模式演化

新模式

写入

读取

操作

增加的字段

通过默认值读取新字段,因为写入时没有该字段

读取时不知道新写人的新字段,所以忽略该字段(投影)

删除的字段

读取时忽略已删除的字段(投影)

写入时不写入已删除的字段。如果旧模式对该字段有 默认值,那么读取时可以使用该默认值,否则报错。 在这种情况下,最好同时更新读取模式或在更新写人 模式之前更新读取模式

Avro模式演化的另一个有用的技术是使用别名。别名允许你在读取Avro数据的模式与写入Avro数据的模式中使用不同的名称。例如,下列读取模式可以使用新的字段名称(即firstsecond),来读取StringPair数据,而非写入数据时使用的字段名称(leftright)。

{
    "type": "record",
    "name": "StringPair",
    "doc": "A pair of strings with aliased field names.",
    "fields":[
        {"name": "first", "type": "string", "aliases": ["left"]},
        {"name": "second", "type": "string", "aliases": ["right"]}
    ]
}

注意,别名的主要作用是将写入模式转换(在读取的时候)为读取模式,但是别名对读取程序是不可见的。在上述例子中,读取程序无法再使用字段名称leftright,因为它们已经被转换为firstsecond

转载请注明:全栈大数据 » 4.4.5模式的解析

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址