【问题标题】:Avro schema not respecting alias in schema definitionAvro 架构不尊重架构定义中的别名
【发布时间】:2021-09-20 15:36:42
【问题描述】:

Avro 架构schema.avsc:

{
    "namespace": "standard",
    "type": "record",
    "name": "agent",
    "aliases":["agents"],
    "fields": [
        {
            "name": "id",
            "type": ["string", "null"]
        },
        {
            "name": "name",
            "type": ["string", "null"],
            "aliases":["title", "nickname"]
        }
    ]
}

Python 脚本main.py:

from fastavro import writer, reader
from fastavro.schema import load_schema

schema = load_schema('schema.avsc')
avro_data = 'agent.avro'
data = jsonlines.open('data.jsonl')

with open(avro_data, 'wb') as fout:
    writer(fout, schema, data, validator=True)

with open(avro_data, 'rb') as fin:
    for i in reader(fin, schema):
        print(i)

当我的 json 行 data.jsonl 文件看起来像这样时:

{"id":"1","name":"foo"}
{"id":"2","name":"bar"}

我的 python 脚本返回:

{'id': '1', 'name': 'foo'}
{'id': '2', 'name': 'bar'}

但是,如果我的 json 行 data.jsonl 文件看起来像这样:

{"id":"1","title":"foo"}
{"id":"2","title":"bar"}

我的 python 脚本返回:

{'id': '1', 'name': None}
{'id': '2', 'name': None}

知道为什么 name 列不尊重我在 avro 架构文件中为该特定字段定义的 aliases 属性吗?

【问题讨论】:

    标签: python avro


    【解决方案1】:

    当您使用旧架构编写的数据要使用新架构读取时,将使用别名。您的示例仅使用一种模式,因此别名不适用于仅一种模式。

    让我们在示例中使用以下两种模式。这是一个使用 title 字段的“旧”模式:

    old_schema.avsc

    {
        "namespace": "standard",
        "type": "record",
        "name": "agent",
        "aliases":["agents"],
        "fields": [
            {
                "name": "id",
                "type": ["string", "null"]
            },
            {
                "name": "title",
                "type": ["string", "null"]
            }
        ]
    }
    

    还有一个新架构,我们希望新的 name 字段成为旧 title 字段的别名:

    new_schema.avsc

    {
        "namespace": "standard",
        "type": "record",
        "name": "agent",
        "aliases":["agents"],
        "fields": [
            {
                "name": "id",
                "type": ["string", "null"]
            },
            {
                "name": "name",
                "type": ["string", "null"],
                "aliases":["title"]
            }
        ]
    }
    

    如果我们使用您的第二个 data.jsonl,如下所示:

    {"id":"1","title":"foo"}
    {"id":"2","title":"bar"}
    

    然后我们可以使用您的main.py 的略微修改版本,以便使用旧架构写入数据,然后将新架构传递给reader,以便尊重别名:

    from fastavro import writer, reader
    from fastavro.schema import load_schema
    import jsonlines
    
    old_schema = load_schema('old_schema.avsc')
    new_schema = load_schema('new_schema.avsc')
    avro_data = 'agent.avro'
    data = jsonlines.open('data.jsonl')
    
    # Data is writen with old schema
    with open(avro_data, 'wb') as fout:
        writer(fout, old_schema, data, validator=True)
    
    # And read with new schema
    with open(avro_data, 'rb') as fin:
        for i in reader(fin, new_schema):
            print(i)
    

    现在输出是正确的:

    {'id': '1', 'name': 'foo'}
    {'id': '2', 'name': 'bar'}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-22
      • 2020-05-19
      • 1970-01-01
      • 2021-02-06
      • 2018-02-27
      • 1970-01-01
      • 2021-04-15
      • 1970-01-01
      相关资源
      最近更新 更多