2017-08-22 3 views
5

私は、さまざまな種類のavroスキーマを読み込んで取得する新しいスキーマレジストリをテストしています。テストの過程で、私はさまざまな種類のavroスキーマを作成する必要があります。それは多くの順列を伴うので、私はプログラムでスキーマを作成することに決めました。 私はこのためにApache avro SchemaBuilderを使用しています。apache avro SchemaBuilderを使用して既存のavroスキーマをどのように更新しますか?

私が使用してアブロを作成しました:

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

これは働いていました。

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

は、今私はのようにapacheのアブロライブラリを使用してスキーマの新しいバージョンを作成する:作成したアブロがどのように見えるこのため

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

、私が試した:

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); 

私は:

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) 

私の問題は次のとおりです。

  1. 既存のライブラリを使用して新しいバージョンのスキーマを追加するにはどうすればよいですか?
  2. スキーマを作成するためにavro schemaBuilderを使用するか、独自のPOJOを作成してスキーマを構築するか、avscファイルをデータディレクトリに保存する必要があります。

答えて

0

あなたは多分それは不器用だ、フィールドを作成し、これを試すことができます。

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

あなたは@xipingとして、各分野の深いコピーをしなければならない新しいものに古いスキーマからフィールドをコピーするには提案された。

Schemaクラスは、フィールドがスキーマに一度だけ追加されていることを確認します。その場合、フィールドはすでに古いスキーマに追加されています。あなたは、彼らがAvro 1.7.7からこのスニペットにフラグを使用する方法を見ることができます

@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; 
} 
関連する問題