如何在休眠搜索中索引复合主键 [英] How to index composite primary keys in hibernate search
问题描述
我具有以下类定义,对于类UserAdAccount,它同时使用adAccountId和userId作为其复合主键.我需要使用此复合主键作为索引的文档ID.
在阅读《 Hibernate Search 5.11.5.Final:参考指南》(这是我正在使用的版本)之后,我发现了以下内容:功能更强大的TwoWayFieldBridge界面允许您将多个字段存储到索引中,这对于复合属性很有用,但实现起来较为复杂.
我不确定如何继续使用TwoWayFieldBridge在这里解决我的需求.感谢您的帮助!
@Entity(名称="JHI_USER_AD_ACCOUNT")@索引@IdClass(UserAdAccountId.class)@盖特@Setter公共类UserAdAccount实现SearchableEntity,可序列化{//新添加的带有双向字符串桥的id字段@DocumentId@Column(名称="ID")@FieldBridge(impl = UserAdAccoutPrimaryKeyBridge.class)私人UserAdAccountId ID;@ID@Column(名称="AD_ACCOUNT_ID")@GenericGenerator(name ="native",strategy ="native")@场地私人Long adAccountId;@ID@Column(名称="USER_ID")@GenericGenerator(name ="native",strategy ="native")@场地私有Long userId;@多多@JoinColumn(名称="USER_ID",referencedColumnName ="ID",可更新=假,可插入=假)@JsonIgnore私人用户用户;@多多@JoinColumn(名称="AD_ACCOUNT_ID",referencedColumnName ="ID",可更新=假,可插入=假)@IndexedEmbedded(includePaths ="name")私人AdAccount adAccount;}@盖特@Setter@EqualsAndHashCode(of = {"userId","adAccountId"})公共类UserAdAccountId实现Serializable {私有Long userId;私人Long adAccountId;}公共类UserAdAccoutPrimaryKeyBridge实现TwoWayStringBridge {@Overridepublic String objectToString(Object object){UserAdAccountId userAdAccountId =(UserAdAccountId)对象;StringBuilder buffer = new StringBuilder();buffer.append(userAdAccountId.getUserId()).append(-").append(userAdAccountId.getAdAccountId());返回buffer.toString();}@Override公共对象stringToObject(String value){String []组件= value.split(-");UserAdAccountId userAdAccountId = new UserAdAccountId();userAdAccountId.setUserId(Long.parseLong(components [0]));userAdAccountId.setAdAccountId(Long.parseLong(components [1]));返回userAdAccountId;}}
来自文档:
双向过程很重要,即:[...]
- 对于TwoWayFieldBridge:对于给定的文档,由get()返回的对象必须与最初传递给set()的对象相同.
此外,为了使TwoWayFieldBridge实现在文档标识符上使用时正确运行,void set(String name,Object value,Document document,LuceneOptions luceneOptions)方法必须遵循以下约定向文档添加字段:>
- 字段名称必须是name参数中提供的名称
- 该字段值必须编码为字符串
- 字段值必须与value参数的给定值唯一
- 字段值必须与给定value参数的objectToString方法返回的值匹配.
您可以找到复合主键的示例实现 或者,如果您确定ID的组成部分不包含某个字符串,则可以将该字符串用作ID的索引形式的分隔符,并且可以进行转换索引形式返回到原始ID.这意味着您可以使用更简单的 I have the following class definitions and for class UserAdAccount, it uses both the adAccountId and userId as its composite primary key. I need to use this composite primary key as the document id for indexing. After reading the Hibernate Search 5.11.5.Final: Reference Guide(This is the version I am using), I found the following:
The more powerful TwoWayFieldBridge interface allows you to store more than one field into the index, which can be useful for composite properties, but is more complex to implement. I am not sure how to proceed using the TwoWayFieldBridge to address my need here. Any help is appreciated!
From the documentation: It is important for the two-way process to be idempotent, i.e.:
[...] Also, in order for TwoWayFieldBridge implementations to work correctly when used on a document identifier, the void set(String name, Object value, Document document, LuceneOptions luceneOptions) method must add a field to the document following these conventions: You can find an example implementation for a composite primary key on github: Alternatively, if you're certain the components of your ID don't contain a certain string, you will be able to use that string as a separator for the indexed form of your ID, and you'll be able to convert that indexed form back to the original ID. This means you can use the simpler
这篇关于如何在休眠搜索中索引复合主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!公共类PersonPKBridge实现TwoWayFieldBridge,MetadataProvidingFieldBridge {私有静态最终字符串FIRST_NAME_SUFFIX ="_content.firstName";私有静态最终字符串LAST_NAME_SUFFIX ="_content.lastName";@Override公共无效configureFieldMetadata(字符串名称,FieldMetadataBuilder构建器){builder.field(名称+ FIRST_NAME_SUFFIX,FieldType.STRING).field(name + LAST_NAME_SUFFIX,FieldType.STRING);}@Overridepublic Object get(字符串名称,文档文档){PersonPK id =新的PersonPK();IndexableField字段= document.getField(名称+ FIRST_NAME_SUFFIX);id.setFirstName(field.stringValue());字段= document.getField(名称+ LAST_NAME_SUFFIX);id.setLastName(field.stringValue());返回ID;}@Overridepublic String objectToString(Object object){PersonPK id =(PersonPK)对象;StringBuilder sb = new StringBuilder();sb.append(id.getFirstName()).append(").append(id.getLastName());返回sb.toString();}@Override公共无效集(字符串名称,对象值,文档文档,LuceneOptions luceneOptions){PersonPK id =(PersonPK)值;//将每个属性存储在唯一的字段中luceneOptions.addFieldToDocument(name + FIRST_NAME_SUFFIX,id.getFirstName(),document);luceneOptions.addFieldToDocument(name + LAST_NAME_SUFFIX,id.getLastName(),document);//将唯一的字符串表示形式存储在指定的字段中luceneOptions.addFieldToDocument(name,objectToString(id),document);复制代码}}
TwoWayStringBridge
并依靠串联/拆分:
公共类PersonPKBridge实现TwoWayStringBridge {@Overridepublic String objectToString(Object object){PersonPK id =(PersonPK)对象;StringBuilder sb = new StringBuilder();sb.append(id.getFirstName()).append(").append(id.getLastName());返回sb.toString();}@Override公共对象stringToObject(String value){String []组件= value.split(");PersonPK id =新的PersonPK();id.setFirstName(components [0]);id.setLastName(components [1]);返回ID;}}
@Entity (name = "JHI_USER_AD_ACCOUNT")
@Indexed
@IdClass(UserAdAccountId.class)
@Getter
@Setter
public class UserAdAccount implements SearchableEntity, Serializable {
//newly added id field with two way string bridge
@DocumentId
@Column(name = "ID")
@FieldBridge(impl = UserAdAccoutPrimaryKeyBridge.class)
private UserAdAccountId id;
@Id
@Column(name = "AD_ACCOUNT_ID")
@GenericGenerator( name = "native", strategy = "native")
@Field
private Long adAccountId;
@Id
@Column(name = "USER_ID")
@GenericGenerator( name = "native", strategy = "native")
@Field
private Long userId;
@ManyToOne
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", updatable = false, insertable = false)
@JsonIgnore
private User user;
@ManyToOne
@JoinColumn(name = "AD_ACCOUNT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
@IndexedEmbedded(includePaths = "name")
private AdAccount adAccount;
}
@Getter
@Setter
@EqualsAndHashCode(of = {"userId", "adAccountId"})
public class UserAdAccountId implements Serializable {
private Long userId;
private Long adAccountId;
}
public class UserAdAccoutPrimaryKeyBridge implements TwoWayStringBridge {
@Override
public String objectToString(Object object) {
UserAdAccountId userAdAccountId = (UserAdAccountId) object;
StringBuilder buffer = new StringBuilder();
buffer.append(userAdAccountId.getUserId()).append("-").append(userAdAccountId.getAdAccountId());
return buffer.toString();
}
@Override
public Object stringToObject(String value) {
String[] components = value.split("-");
UserAdAccountId userAdAccountId = new UserAdAccountId();
userAdAccountId.setUserId(Long.parseLong(components[0]));
userAdAccountId.setAdAccountId(Long.parseLong(components[1]));
return userAdAccountId;
}
}
public class PersonPKBridge implements TwoWayFieldBridge, MetadataProvidingFieldBridge {
private static final String FIRST_NAME_SUFFIX = "_content.firstName";
private static final String LAST_NAME_SUFFIX = "_content.lastName";
@Override
public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
builder.field( name + FIRST_NAME_SUFFIX, FieldType.STRING )
.field( name + LAST_NAME_SUFFIX, FieldType.STRING );
}
@Override
public Object get(String name, Document document) {
PersonPK id = new PersonPK();
IndexableField field = document.getField( name + FIRST_NAME_SUFFIX );
id.setFirstName( field.stringValue() );
field = document.getField( name + LAST_NAME_SUFFIX );
id.setLastName( field.stringValue() );
return id;
}
@Override
public String objectToString(Object object) {
PersonPK id = (PersonPK) object;
StringBuilder sb = new StringBuilder();
sb.append( id.getFirstName() ).append( " " ).append( id.getLastName() );
return sb.toString();
}
@Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
PersonPK id = (PersonPK) value;
//store each property in a unique field
luceneOptions.addFieldToDocument( name + FIRST_NAME_SUFFIX, id.getFirstName(), document );
luceneOptions.addFieldToDocument( name + LAST_NAME_SUFFIX, id.getLastName(), document );
//store the unique string representation in the named field
luceneOptions.addFieldToDocument( name, objectToString( id ), document );
}
}
TwoWayStringBridge
and rely on concatenation/splitting:public class PersonPKBridge implements TwoWayStringBridge {
@Override
public String objectToString(Object object) {
PersonPK id = (PersonPK) object;
StringBuilder sb = new StringBuilder();
sb.append( id.getFirstName() ).append( " " ).append( id.getLastName() );
return sb.toString();
}
@Override
public Object stringToObject(String value) {
String[] components = value.split(" ");
PersonPK id = new PersonPK();
id.setFirstName( components[0] );
id.setLastName( components[1] );
return id;
}
}