español - ¿Puedo dividir un esquema de Apache Avro en varios archivos?
avro format (6)
Puedo hacer,
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": {
"type": "record",
"name": "Bar",
"fields": [ ]
}}
]
}
y eso funciona bien, pero suponiendo que quiero dividir el esquema en dos archivos como:
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": "Bar"}
]
}
{
"type": "record",
"name": "Bar",
"fields": [ ]
}
¿Tiene Avro la capacidad para hacer esto?
De lo que he podido averiguar hasta ahora, no.
Hay un buen artículo sobre alguien que codificó su propio método para hacer esto aquí:
Debe importar el archivo avsc en el complemento avro-maven, donde primero escribió el esquema del objeto que desea reutilizar
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>${avro.maven.plugin.version}</version>
<configuration>
<stringType>String</stringType>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>src/main/java/com/xyz/avro</sourceDirectory> // Avro directory
<imports>
<import>src/main/java/com/xyz/avro/file.avsc</import> // Import here
</imports>
</configuration>
</execution>
</executions>
El orden de las importaciones en el pom.xml importa. Debe importar los subtipos primero antes de procesar el resto.
<imports>
<import>${project.basedir}/src/main/resources/avro/Bar.avro</import>
<import>${project.basedir}/src/main/resources/avro/Foo.avro</import>
</imports>
Eso desbloquearía el código para que undefined name: Bar.avro
error de undefined name: Bar.avro
.
Si es posible.
Lo he hecho en mi proyecto java definiendo archivos de esquema comunes en avro-maven-plugin Ejemplo:
search_result.avro:
{"namespace": "com.myorg.other",
"type": "record",
"name": "SearchResult",
"fields": [
{"name": "type", "type": "SearchResultType"},
{"name": "keyWord", "type": "string"},
{"name": "searchEngine", "type": "string"},
{"name": "position", "type": "int"},
{"name": "userAction", "type": "UserAction"}
]
}
search_suggest.avro:
{"namespace": "com.myorg.other",
"type": "record",
"name": "SearchSuggest",
"fields": [
{"name": "suggest", "type": "string"},
{"name": "request", "type": "string"},
{"name": "searchEngine", "type": "string"},
{"name": "position", "type": "int"},
{"name": "userAction", "type": "UserAction"},
{"name": "timestamp", "type": "long"}
]
}
user_action.avro:
{"namespace": "com.myorg.other",
"type": "enum",
"name": "UserAction",
"symbols": ["S", "V", "C"]
}
search_result_type.avro
{"namespace": "com.myorg.other",
"type": "enum",
"name": "SearchResultType",
"symbols": ["O", "S", "A"]
}
configuración de avro-maven-plugin:
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.7.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/resources/avro</sourceDirectory>
<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
<includes>
<include>**/*.avro</include>
</includes>
<imports>
<import>${project.basedir}/src/main/resources/avro/user_action.avro</import>
<import>${project.basedir}/src/main/resources/avro/search_result_type.avro</import>
</imports>
</configuration>
</execution>
</executions>
</plugin>
Supongo que su motivación es (como la mía) estructurar su definición de esquema y evitar copiar y pegar errores.
Para lograrlo, también puede utilizar Avro IDL . Permite definir esquemas avro en un nivel superior. La reutilización de tipos es posible dentro del mismo archivo y también a través de múltiples archivos .
Para generar la ejecución de los archivos .avsc
$ java -jar avro-tools-1.7.7.jar idl2schemata my-protocol.avdl
Los archivos .avsc resultantes tendrán un aspecto similar al de su ejemplo inicial, pero a medida que se generen a partir del archivo .avdl, no se perderán en el formato json detallado.
También puede definir múltiples esquemas dentro de un archivo:
schemas.avsc:
[
{
"type": "record",
"name": "Bar",
"fields": [ ]
},
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": "Bar"}
]
}
]
Si quiere reutilizar los esquemas en varios lugares, esto no es muy bueno, pero en mi opinión mejora mucho la legibilidad y la capacidad de mantenimiento.