【问题标题】:Recursive data type like a tree as Avro schema递归数据类型,如 Avro 模式的树
【发布时间】:2018-04-01 01:20:23
【问题描述】:

阅读https://avro.apache.org/docs/current/spec.html 它说架构必须是以下之一:

  • 一个 JSON 字符串,命名一个定义的类型。
  • 一个 JSON 对象,格式为: {"type": "typeName" ...attributes...} 其中typeName 是 原始或派生类型名称,定义如下。属性不 本文档中定义的允许作为元数据,但不得 影响序列化数据的格式。
  • 一个 JSON 数组,代表一个 嵌入类型的联合。

我想要一个描述树的模式,使用树的递归定义:

  • 具有值(例如整数)和树列表​​(子节点)的节点
  • 有值的叶子

我最初的尝试是这样的:

{
  "name": "Tree",
  "type": [
    {
      "name": "Node",
      "type": "record",
      "fields": [
        {
          "name": "value",
          "type": "long"
        },
        {
          "name": "children",
          "type": { "type": "array", "items": "Tree" }
        }
      ]
    },
    {
      "name": "Leaf",
      "type": "record",
      "fields": [
        {
          "name": "value",
          "type": "long"
        }
      ]
    }
  ]
}

但是 Avro 编译器拒绝了这个,抱怨没有 {"name":"Tree","type":[{"name":"Node"... 类型的东西。似乎 Avro 不喜欢顶层的联合类型。我猜这属于前面提到的规则“模式必须是...... JSON 对象......其中 typeName 是原始类型名称或派生类型名称之一。”我不确定“派生类型名称”是什么。起初我认为它与“复杂类型”相同,但包括联合类型..

无论如何,将其更改为更复杂的定义:

{
  "name": "Tree",
  "type": "record",
  "fields": [{
    "name": "ctors",
    "type": [
      {
        "name": "Node",
        "type": "record",
        "fields": [
          {
            "name": "value",
            "type": "long"
          },
          {
            "name": "children",
            "type": { "type": "array", "items": "Tree" }
          }
        ]
      },
      {
        "name": "Leaf",
        "type": "record",
        "fields": [
          {
            "name": "value",
            "type": "long"
          }
        ]
      }
    ]
  }]
}

有效,但现在我有这个奇怪的记录,只有一个字段,其唯一目的是让我定义我想要的顶级联合类型。

这是在 Avro 中获得我想要的唯一方法还是有更好的方法?

谢谢!

【问题讨论】:

    标签: protocols avro recursive-datastructures


    【解决方案1】:

    我只是偶然发现了想要定义递归联合的相同问题。我对比您的复杂解决方案更清洁的解决方案感到非常悲观,因为目前没有办法命名一个联合,因此在构造它时无法递归引用它,请参阅open ticket

    【讨论】:

      【解决方案2】:

      如果您将Tree 表示为一个节点,将Leaf 表示为一个具有空子列表的节点,您可以完全避免命名联合问题,并使用一种递归类型非常简单地做到这一点:

      {
        "type": "record",
        "name": "TreeNode",
        "fields": [
          {
            "name": "value",
            "type": "long"
          },
          {
            "name": "children",
            "type": { "type": "array", "items": "TreeNode" }
          }
        ]
      }
      
      

      现在,你的TreeNodeLeaf三种类型统一为一种TreeNode,不需要NodeLeaf的联合。

      【讨论】:

        猜你喜欢
        • 2021-12-19
        • 2021-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多