使用休眠搜索的自定义桥时出错
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",...);
...
我有两个实体:
@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",...);
...