Ошибка при использовании пользовательского моста hibernate-search - PullRequest
2 голосов
/ 15 января 2020

У меня есть две сущности:

@Indexed
@Entity
@Table(name = "LK_CONTACT_TYPE")
public class ContactTypeEntity {
    @Id
    @Column(name = "ID")
    @DocumentId
    Integer id;

    @SortableField
    @Field(store = Store.YES, bridge = @FieldBridge(impl = ContactTypeComparator.class))
    @Column(name = "NAME")
    String name; 

    getter() .. setter()..
}



@Indexed
 @Entity
 @Table(name = "DIRECTORY")
 public class DirectoryEntity {
    ....
    @IndexedEmbedded(prefix = "contactType.", includePaths = {"id", "name"})
    @ManyToOne
    @JoinColumn(name = "CONTACT_TYPE")
    private ContactTypeEntity contactType;

    getter() ... setter()...
}

public class ContactTypeComparator implements MetadataProvidingFieldBridge, TwoWayStringBridge {

     @Override
    public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
        if ( value != null ) {
          int ordinal = getOrdinal(value.toString());
          luceneOptions.addNumericFieldToDocument(name, ordinal, document);
        }
    }

    @Override
    public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
        builder.field(name, FieldType.INTEGER).sortable(true);
    }

    private int getOrdinal(ContactType value) {
        switch( value ) {
          case PBX: return 0;
          case TEL: return 1;
          case GSM: return 2;
          case FAX: return 3;
          default: return 4;
        }
    }


    @Override
    public Object get(String name, Document document) {
    return document.get( name );
   }

    @Override
    public String objectToString(Object object) {
    return object.toString();
   }
}

и часть запроса:

...
query.setSort(queryBuilder.sort().byScore().andByField("contactType.name").createSort());
query.setProjection(... , "contactType.name",...);
...

Я получаю следующую ошибку: java .lang.IllegalStateException: неожиданные значения документа введите NONE в поле contactType.name (ожидается = NUMERI C). Используйте UninvertingReader или индекс с docvalues.

Примечание. Я использую hibernate-search 5.10. Я хочу показать contactType.name имя в интерфейсе вместо номера. Для более подробной информации

1 Ответ

1 голос
/ 16 января 2020

Кажется, что мое первоначальное предложение немного пропущено в методе set(), чтобы добавить значения документа:


     @Override
    public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
        if ( value != null ) {
          int ordinal = getOrdinal(value.toString());
          luceneOptions.addNumericFieldToDocument(name, ordinal, document);
          // ADD THIS
          luceneOptions.addNumericDocValuesFieldToDocument(name, ordinal, document);
        }
    }

Кроме того, если вам нужно использовать поле для сортировки и проекция, я бы рекомендовал объявить два поля. В противном случае проекция вернет целые числа, а это не то, что вам нужно.

Итак, сделайте это:

@Indexed
@Entity
@Table(name = "LK_CONTACT_TYPE")
public class ContactTypeEntity {
    @Id
    @Column(name = "ID")
    @DocumentId
    Integer id;

    @SortableField
    // CHANGE THESE TWO LINES
    @Field(store = Store.YES)
    @Field(name = "name_sort", bridge = @FieldBridge(impl = ContactTypeComparator.class))
    @Column(name = "NAME")
    String name; 

    getter() .. setter()..
}



@Indexed
 @Entity
 @Table(name = "DIRECTORY")
 public class DirectoryEntity {
    ....
    // CHANGE THIS LINE
    @IndexedEmbedded(prefix = "contactType.", includePaths = {"id", "name", "name_sort"})
    @ManyToOne
    @JoinColumn(name = "CONTACT_TYPE")
    private ContactTypeEntity contactType;

    getter() ... setter()...
}

public class ContactTypeComparator implements MetadataProvidingFieldBridge, TwoWayStringBridge {

     @Override
    public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
        if ( value != null ) {
          int ordinal = getOrdinal(value.toString());
          luceneOptions.addNumericFieldToDocument(name, ordinal, document);
          // ADD THIS LINE
          luceneOptions.addNumericDocValuesFieldToDocument(name, ordinal, document);
        }
    }

    @Override
    public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
        builder.field(name, FieldType.INTEGER).sortable(true);
    }

    private int getOrdinal(ContactType value) {
        switch( value ) {
          case PBX: return 0;
          case TEL: return 1;
          case GSM: return 2;
          case FAX: return 3;
          default: return 4;
        }
    }


    @Override
    public Object get(String name, Document document) {
    return document.get( name );
   }

    @Override
    public String objectToString(Object object) {
    return object.toString();
   }
}

Затем запросите вот так:

...
query.setSort(queryBuilder.sort().byScore().andByField("contactType.name_sort").createSort());
query.setProjection(... , "contactType.name",...);
...
...