#python #avro
Вопрос:
Avro schema 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)
Когда мой data.jsonl
файл строк json выглядит следующим образом:
{"id":"1","name":"foo"}
{"id":"2","name":"bar"}
Мой скрипт на python возвращает:
{'id': '1', 'name': 'foo'}
{'id': '2', 'name': 'bar'}
Однако, если мой data.jsonl
файл строк json выглядит следующим образом:
{"id":"1","title":"foo"}
{"id":"2","title":"bar"}
Мой скрипт на python возвращает:
{'id': '1', 'name': None}
{'id': '2', 'name': None}
Есть идеи, почему name
столбец не соответствует aliases
атрибуту, который я определил в файле схемы 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'}