2017-08-22 14 views
5

Tôi đang thử nghiệm một đăng ký lược đồ mới để tải và truy xuất các loại lược đồ avro khác nhau. Trong quá trình thử nghiệm, tôi cần tạo một loạt các loại lược đồ avro khác nhau. Vì nó liên quan đến rất nhiều hoán vị, tôi quyết định tạo lược đồ theo lập trình. Tôi đang sử dụng apache avro SchemaBuilder để làm như vậy.Làm cách nào để bạn cập nhật lược đồ avro hiện có bằng apache avro SchemaBuilder?

tôi tạo ra các Avro sử dụng:

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

này làm việc. Các Avro tạo trông giống như:

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

Bây giờ tôi muốn tạo ra một phiên bản mới của giản đồ bằng cách sử dụng thư viện apache Avro như:

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

Đối với điều này, tôi đã cố gắng:

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

Tôi nhận được:

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) 

Vấn đề của tôi là:

  1. Làm cách nào để thêm phiên bản mới của lược đồ bằng thư viện hiện có?
  2. Tôi có nên sử dụng lược đồ avBuilder để tạo lược đồ hay đúng hơn là tạo các POJO của riêng tôi để xây dựng lược đồ/lưu tệp avsc trong một thư mục dữ liệu.

Trả lời

0

Bạn có thể thử này để tạo ra các lĩnh vực, có lẽ đó là vụng về:

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

Để sao chép các lĩnh vực từ giản đồ cũ sang cái mới bạn phải làm một bản sao sâu sắc về từng lĩnh vực như @xiping xing gợi ý.

Điều này là do lớp Schema kiểm tra rằng trường chỉ được thêm một lần vào một lược đồ và trong trường hợp của bạn, các trường đó đã được thêm vào lược đồ cũ.

Bạn có thể xem cách họ sử dụng một lá cờ trong đoạn này từ 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; 
} 
Các vấn đề liên quan