2017-08-22 1 views
5

Ich teste eine neue Schema-Registrierung, die verschiedene Arten von Avro-Schemas lädt und abruft. Während des Tests muss ich eine Reihe verschiedener Arten von Avro-Schemas erstellen. Da es viele Permutationen beinhaltet, entschied ich mich, das Schema programmatisch zu erstellen. Ich verwende den Apache avro SchemaBuilder, um dies zu tun.Wie aktualisierst du ein bestehendes avro-Schema mit apache avro SchemaBuilder?

habe ich die Avro mit:

Schema oldSchema = SchemaBuilder 
     .record("abc") 
     .aliases("records") 
     .fields() 
     .name("field_null") 
     .type("null") 
     .noDefault() 
     .endRecord(); 

Das funktionierte. Die Avro erstellt wie folgt aussieht: mit den Apache avro Bibliotheken wie

{ 
"type" : "record", 
"name" : "abc", 
"fields" : [ { 
    "name" : "field_null", 
    "type" : "null" 
    } ], 
    "aliases" : [ "records" ] 
} 

Jetzt möchte ich eine neue Version des Schemas erstellen:

{ 
"type" : "record", 
"name" : "abc", 
"fields" : [ { 
    "name" : "field_null", 
    "type" : "null" 
    }, 
    { 
    "name" : "new_field", 
    "type" : "int", 
    "default" : 10 
    } 
], 
"aliases" : [ "records" ] 
} 

Dazu habe ich versucht:

Schema.Field field = new Schema.Field("new_field", SchemaBuilder.builder().intType(), 
    "NewField", 10); 

List<Schema.Field> fields = new ArrayList<>(); 
fields.add(field); 
fields.addAll(oldSchema.getFields()); 

Schema record = Schema.createRecord(oldSchema.getName(), 
    "Changes", 
    oldSchema.getNamespace(), 
    false, 
    fields); 

Ich bekomme:

org.apache.avro.AvroRuntimeException: Field already used: field_null type:NULL pos:0 

at org.apache.avro.Schema$RecordSchema.setFields(Schema.java:647) 
at org.apache.avro.Schema$RecordSchema.<init>(Schema.java:618) 
at org.apache.avro.Schema.createRecord(Schema.java:167) 

Mein Problem ist:

  1. Wie füge ich neue Versionen des Schemas mit vorhandenen Bibliotheken hinzu?
  2. Soll ich avro SchemaBuilder verwenden, um das Schema zu erstellen oder lieber meine eigenen POJOs zu erstellen, um das Schema zu erstellen/speichern Sie die AVSC-Dateien in einem Datenverzeichnis.

Antwort

0

Sie können versuchen, diese Felder zu erstellen, vielleicht ungeschickt es ist:

Schema.Field field = new Schema.Field("new_field",SchemaBuilder.builder().intType(), 
    "NewField", 10); 

List<Schema.Field> fields = new ArrayList<>(); 

for (Schema.Field f : oldSchema.getFields()) { 

    Schema.Field _field = new Schema.Field(f.name(), f.schema(), f.doc(), f.defaultValue()); 
    fields.add(_field); 

} 
0

die Felder aus dem alten Schema auf die neue kopieren Sie als @xiping eine tiefe Kopie der einzelnen Felder zu tun haben Xing vorgeschlagen.

Dies ist, weil die Schema Klasse überprüft, dass das Feld nur einmal zu einem Schema hinzugefügt wird, und in Ihrem Fall wurden diese Felder bereits zu dem alten Schema hinzugefügt.

Sie können sehen, wie sie einen Flag in diesem Ausschnitt aus Avro 1.7.7 verwenden:

@Override 
public void setFields(List<Field> fields) { 
    if (this.fields != null) { 
    throw new AvroRuntimeException("Fields are already set"); 
    } 
    int i = 0; 
    fieldMap = new HashMap<String, Field>(); 
    LockableArrayList ff = new LockableArrayList(); 
    for (Field f : fields) { 
    if (f.position != -1) 
     throw new AvroRuntimeException("Field already used: " + f); 
    f.position = i++; 
    final Field existingField = fieldMap.put(f.name(), f); 
    if (existingField != null) { 
     throw new AvroRuntimeException(String.format(
      "Duplicate field %s in record %s: %s and %s.", 
      f.name(), name, f, existingField)); 
    } 
    ff.add(f); 
    } 
    this.fields = ff.lock(); 
    this.hashCode = NO_HASHCODE; 
} 
Verwandte Themen