2015-09-18 2 views
5

Я имею дело с журналами сервера, которые являются JSON-форматом, и я хочу хранить свои журналы на AWS S3 в формате Паркет (а Паркет требует схему Avro). Во-первых, все журналы имеют общий набор полей, во-вторых, во всех журналах есть много необязательных полей, которые не входят в общий набор.Как смешивать запись с картой в Avro?

Например, происходит некорректно три бревна:

{ "ip": "172.18.80.109", "timestamp": "2015-09-17T23:00:18.313Z", "message":"blahblahblah"} 
{ "ip": "172.18.80.112", "timestamp": "2015-09-17T23:00:08.297Z", "message":"blahblahblah", "microseconds": 223} 
{ "ip": "172.18.80.113", "timestamp": "2015-09-17T23:00:08.299Z", "message":"blahblahblah", "thread":"http-apr-8080-exec-1147"} 

Все из трех бревен 3 общие поля: ip, timestamp и message, некоторые из бревен имеют дополнительные поля, такие как microseconds и thread.

Если я использую следующую схему, то я потеряю все дополнительные поля .:

{"namespace": "example.avro", 
"type": "record", 
"name": "Log", 
"fields": [ 
    {"name": "ip", "type": "string"}, 
    {"name": "timestamp", "type": "String"}, 
    {"name": "message", "type": "string"} 
] 
} 

И следующая схема работает отлично:

{"namespace": "example.avro", 
"type": "record", 
"name": "Log", 
"fields": [ 
    {"name": "ip", "type": "string"}, 
    {"name": "timestamp", "type": "String"}, 
    {"name": "message", "type": "string"}, 
    {"name": "microseconds", "type": [null,long]}, 
    {"name": "thread", "type": [null,string]} 
] 
} 

Но единственная проблема в том, что я не знайте все имена необязательных полей, если я не сканирую все журналы, кроме того, в будущем появятся новые дополнительные поля.

Тогда я придумываю идею, которая сочетает в себе record и map:

{"namespace": "example.avro", 
"type": "record", 
"name": "Log", 
"fields": [ 
    {"name": "ip", "type": "string"}, 
    {"name": "timestamp", "type": "String"}, 
    {"name": "message", "type": "string"}, 
    {"type": "map", "values": "string"} // error 
] 
} 

К сожалению, это не будет компилироваться:

java -jar avro-tools-1.7.7.jar compile schema example.avro . 

Он выкинет ошибку:

Exception in thread "main" org.apache.avro.SchemaParseException: No field name: {"type":"map","values":"long"} 
    at org.apache.avro.Schema.getRequiredText(Schema.java:1305) 
    at org.apache.avro.Schema.parse(Schema.java:1192) 
    at org.apache.avro.Schema$Parser.parse(Schema.java:965) 
    at org.apache.avro.Schema$Parser.parse(Schema.java:932) 
    at org.apache.avro.tool.SpecificCompilerTool.run(SpecificCompilerTool.java:73) 
    at org.apache.avro.tool.Main.run(Main.java:84) 
    at org.apache.avro.tool.Main.main(Main.java:73) 

Есть ли способ хранить строки JSON в формате Avro, которые являются гибкими le, чтобы иметь дело с неизвестными необязательными полями?

В основном это Схема эволюции проблема, Spark может решить эту проблему на Schema Merging. Я ищу решение с Hadoop.

+0

Ваша карта не имеет атрибута имени. Дайте ему это. :) – oakad

+0

Думаю, вы никогда не пробовали авро. Это не сработает. '{" namespace ":" example.avro ", " type ":" record ", " name ":" Log ", " fields ": [ {" name ":" ip "," type ": "string"}, {"name": "timestamp", "type": "string"}, {"name": "message", "type": "string"}, {"name": " addtional "," type ":" map "," values ​​":" string "} ] }' – soulmachine

ответ

5

Тип карты является «сложным» типом в авро терминологии. Ниже приведен фрагмент работ:

{"namespace": "example.avro", 
"type": "record", 
"name": "Log", 
"fields": [ 
    {"name": "ip", "type": "string"}, 
    {"name": "timestamp", "type": "string"}, 
    {"name": "message", "type": "string"}, 
    {"name": "additional", "type": {"type": "map", "values": "string"}} 
    ] 
} 
+0

Спасибо! Эта схема передаст компиляцию. Эта схема помещает все необязательные поля в поле 'addtional', например' {"ip": "172.18.80.109", "timestamp": "2015-09-17T23: 00: 18.313Z", "message": "blah blash "," addtional ": {" microseconds ":" 123 "," thread ":" http-apr-8080-exec-1147 "}}', но я хочу, чтобы все необязательные поля находились на одном уровне общих полей, как три примера журнала в моем вопросе. – soulmachine

+0

Запись в avro определяется как объект с фиксированным числом предопределенных полей. В качестве альтернативы, поместите свою карту в качестве объекта верхнего уровня и обработайте все свои поля в виде ключей на этой карте. – oakad

+0

Если я использую 'map' как тип верхнего уровня, например., '{" type ":" map "," values ​​":" string "}', тогда все поля должны быть 'string', если существуют разные типы полей, тогда' map' беспомощно. – soulmachine

Смежные вопросы