嵌套 Avro 模式

Posted

技术标签:

【中文标题】嵌套 Avro 模式【英文标题】:Nesting Avro schemas 【发布时间】:2017-04-12 18:41:46 【问题描述】:

根据this question关于,嵌套记录模式的正确方法如下:


    "name": "person",
    "type": "record",
    "fields": [
        "name": "firstname", "type": "string",
        "name": "lastname", "type": "string",
        
            "name": "address",
            "type": 
                        "type" : "record",
                        "name" : "AddressUSRecord",
                        "fields" : [
                            "name": "streetaddress", "type": "string",
                            "name": "city", "type": "string"
                        ]
                    ,
        
    ]

我不喜欢给字段命名为 address 并且不得不为字段的架构提供不同的名称 (AddressUSRecord)。我可以为字段和架构提供相同的名称address吗?

如果我想在多个其他模式中使用AddressUSRecord 模式,而不仅仅是person,该怎么办?如果我想在另一个架构中使用AddressUSRecord,比如说business,我是否必须将其命名为其他名称?

理想情况下,我想在单独的架构中定义AddressUSRecord,然后让address 的类型引用AddressUSRecord。但是,尚不清楚 Avro 1.8.1 是否支持这种开箱即用。这个2014 article 表明需要使用自定义代码处理子模式。在 Avro 1.8.1 中定义可重用模式的最佳方法是什么?

注意:我想要一个可以与 Confluent Inc. 的 Schema Registry 配合使用的解决方案。有一个Google Groups thread 似乎表明架构注册表不能很好地处理架构引用。

【问题讨论】:

【参考方案1】:

我可以为字段和架构指定相同的名称、地址吗?

是的,您可以将记录命名为与字段名称相同的名称。

如果我想在多个其他模式中使用 AddressUSRecord 模式,而不仅仅是人呢?

您可以使用多种技术使用多个模式:avro 模式解析器客户端(JVM 和其他)允许您指定多个模式,通常通过 names 参数(Java Schema$Parser/parse 方法允许多个模式 @987654324 @参数)。

然后您可以将依赖模式指定为命名类型:


  "type": "record",
  "name": "Address",
  "fields": [
    
      "name": "streetaddress",
      "type": "string"
    ,
    
      "name": "city",
      "type": "string"
    
  ]

并在父模式之前通过解析器运行它:


  "name": "person",
  "type": "record",
  "fields": [
    
      "name": "firstname",
      "type": "string"
    ,
    
      "name": "lastname",
      "type": "string"
    ,
    
      "name": "address",
      "type": "Address"
    
  ]

顺便说一句,这允许您从单独的文件中进行解析。

或者,您还可以解析以相同方式引用模式的单个联合模式:

[
  
    "type": "record",
    "name": "Address",
    "fields": [
      
        "name": "streetaddress",
        "type": "string"
      ,
      
        "name": "city",
        "type": "string"
      
    ]
  ,
  
    "type": "record",
    "name": "person",
    "fields": [
      
        "name": "firstname",
        "type": "string"
      ,
      
        "name": "lastname",
        "type": "string"
      ,
      
        "name": "address",
        "type": "Address"
      
    ]
  
]

我想要一个可以与 Confluent Inc. 的 Schema Registry 配合使用的解决方案。

架构注册表不支持单独解析架构,但它确实支持解析为联合类型的后一个示例。

【讨论】:

嗨 Niel,我在融合云上尝试完全相同的架构,但是当我在生产者中调用此架构时,我无法使用此架构,即“xxxx.eu-central-1.aws.confluent.cloud" --api-key "xx" --api-secret "xxxxx" 启动 Kafka Producer。 ^C 或 ^D 退出 "firstname": "Joe", "lastname": "Doe", "address": "streetaddress": "somestreet", "city": "somecity" 错误:无法解码文本联合:无法解码文本映射:无法确定编解码器:“名字” 您的 JSON 数组模式确实通过了 avro 验证,但如何使用它?适用于 JSON 对象模式的生产者调用语法不适用于您的提案。谢谢【参考方案2】:

您可以将namespace 设置为记录类型,然后在后续字段中使用namespace.name 作为type 参数。不幸的是,目前无法从其他模式文件中引用类型。

【讨论】:

以上是关于嵌套 Avro 模式的主要内容,如果未能解决你的问题,请参考以下文章

Kafka 的嵌套 Avro 类型是不是有最佳实践?

使用自定义列名将 Avro 文件加载到具有嵌套记录的 GCS

如何将嵌套的 Avro 字段作为单个字段复制到 Redshift?

如何在 Apache Kafka 中使用 AVRO 序列化处理嵌套的源数据?

Spark Sql 查询嵌套记录。我想先过滤嵌套的记录数组,然后爆炸(将它们展开成行)

Mongoose 嵌套模式与嵌套模型