Как использовать avro данные со старым и новым пространством имен

Я столкнулся с проблемой, когда я обновил пространство имен в моем файле схемы avsc. Так как мы использовали общий процессор, созданный в Java, для разбора XML на avro и использовали файл avsc.

Мы разделили интерфейсы и создали 2 разных пространства имен, и теперь имеем 2 одинаковые схемы avsc, только пространство имен отличается.

Поскольку у нас есть данные, которые были созданы с использованием старого пространства имен, я не могу запросить эти данные с новыми данными, сгенерированными с новым пространством имен.

Вот пример моей схемы -

Старая схема - "type" : "record", "name" : "Message", "namespace" : "com.myfirstavsc", "fields" : [ { "name" : "Header",.....**other fields**

Новая схема - "type" : "record", "name" : "Message", "namespace" : "com.mysecondavsc", "fields" : [ { "name" : "Header",.....**other fields**

Когда я запрашиваю свою таблицу улья, я получаю исключение ниже

Failed with exception java.io.IOException:org.apache.avro.AvroTypeException: Found com.myfirstavsc.Property, expecting union

2 ответа

Решение

Я не уверен, как вы пытаетесь прочитать ваши данные, но использование GenericDatumReader должно решить вашу проблему, после чего вы можете преобразовать общую запись в ваши конкретные записи. Я нашел что-то подобное здесь

http://apache-avro.679487.n3.nabble.com/Deserialize-with-different-schema-td4032782.html

http://apache-avro.679487.n3.nabble.com/Deserialize-with- Different-schema-td4032782.html

Ссылка, упомянутая выше, больше не работает, поэтому добавьте объяснение здесь.

Мы получили ту же ошибку в проекте под названием Hudi, поэтому подняли проблему по этому поводу: https://github.com/apache/hudi/issues/7284 .

После устранения неполадок основная причина этого исключенияorg.apache.avro.AvroTypeException: Found hoodie.test_mor_tab.test_mor_tab_record.new_test_col.fixed, expecting unionявляется правилом генератора схемы Avro, оно не может принять изменение пространства имен при обработкеUNIONтип.

Согласно документу Avro Schema Resolution , он может принять эволюцию схемы, если какая-либо схема является объединением в схеме чтения или записи в схеме.GenericDatumReader(Schema writer, Schema reader). Но он не упомянул, что есть еще одно ограничение: полное имя схемы должно быть таким же, если типRECORDилиENUMилиFIXED.

Ссылка на код:

ResolvingGrammarGenerator#bestBranch

      public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
...
  private int bestBranch(Schema r, Schema w, Map<LitS, Symbol> seen) throws IOException {
    Schema.Type vt = w.getType();
      // first scan for exact match
      int j = 0;
      int structureMatch = -1;
      for (Schema b : r.getTypes()) {
        if (vt == b.getType())
          if (vt == Schema.Type.RECORD || vt == Schema.Type.ENUM ||
              vt == Schema.Type.FIXED) {
            String vname = w.getFullName();
            String bname = b.getFullName();
            // return immediately if the name matches exactly according to spec
            if (vname != null && vname.equals(bname))
              return j;

            if (vt == Schema.Type.RECORD &&
                !hasMatchError(resolveRecords(w, b, seen))) {
              String vShortName = w.getName();
              String bShortName = b.getName();
              // use the first structure match or one where the name matches
              if ((structureMatch < 0) ||
                  (vShortName != null && vShortName.equals(bShortName))) {
                structureMatch = j;
              }
            }
          } else
            return j;
        j++;
      }

      // if there is a record structure match, return it
      if (structureMatch >= 0)
        return structureMatch;

      // then scan match via numeric promotion
      j = 0;
      for (Schema b : r.getTypes()) {
        switch (vt) {
        case INT:
          switch (b.getType()) {
          case LONG: case DOUBLE:
            return j;
          }
          break;
        case LONG:
        case FLOAT:
          switch (b.getType()) {
          case DOUBLE:
            return j;
          }
          break;
        case STRING:
          switch (b.getType()) {
          case BYTES:
            return j;
          }
          break;
        case BYTES:
          switch (b.getType()) {
          case STRING:
            return j;
          }
          break;
        }
        j++;
      }
      return -1;
  }
...
}
Другие вопросы по тегам