Mam do czynienia z dziennikami serwera, które są w formacie JSON, i chcę przechowywać moje dzienniki na AWS S3 w formacie Parkiet (i Parkiet wymaga schematu Avro). Po pierwsze, wszystkie dzienniki mają wspólny zestaw pól, po drugie, wszystkie dzienniki mają wiele opcjonalnych pól, których nie ma we wspólnym zestawie.Jak połączyć rekord z mapą w Avro?
Na przykład follwoing trzy dzienniki:
{ "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"}
wszystkich trzech dzienników mają 3 wspólnych pól: ip
, timestamp
i message
niektóre dzienniki mają dodatkowe pola, takie jak microseconds
i thread
.
Gdybym użyć następującego schematu wtedy stracę wszystkie dodatkowe dziedzinach .:
{"namespace": "example.avro",
"type": "record",
"name": "Log",
"fields": [
{"name": "ip", "type": "string"},
{"name": "timestamp", "type": "String"},
{"name": "message", "type": "string"}
]
}
i następujący schemat działa dobrze:
{"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]}
]
}
Ale jedynym problemem jest to, że nie znać wszystkie nazwy pól opcjonalnych, chyba że zeskanuję wszystkie logi, poza tym pojawią się nowe dodatkowe pola w przyszłości.
Potem wymyślić pomysł, który łączy record
i 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
]
}
Niestety nie będzie to skompilować:
java -jar avro-tools-1.7.7.jar compile schema example.avro .
To będzie wyrzucać błąd:
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)
Czy istnieje sposób na przechowywanie ciągów JSON w formacie Avro, które są flexib le radzić sobie z nieznanymi opcjonalnymi polami?
Zasadniczo jest to problem z ewolucją schematu , Spark może poradzić sobie z tym problemem przez Schema Merging. Szukam rozwiązania z Hadoop.
Twoja mapa nie ma atrybutu nazwy. Daj to. :) – oakad
Chyba nigdy nie próbujesz avro. To nie zadziała. '{" 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