使用休眠搜索的自定义桥时出错

Error on using a custom bridge of hibernate-search

我有两个实体:

@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:字段 'contactType.name' 的意外文档值类型 NONE(预期=NUMERIC)。使用 UninvertingReader 或索引与 docvalues.

注意:我使用的是 hibernate-search 5.10。 我想在 UI 上显示 contactType.name 姓名而不是号码。

似乎我最初的建议在 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);
        }
    }

最重要的是,如果您需要将字段用于排序和投影,我建议声明 两个 字段。否则投影将 return 整数,这不是你想要的。

所以,这样做:

@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",...);
...