如何在休眠搜索中索引复合主键

时间:2020-07-30 22:44:53

标签: hibernate-search

我具有以下类定义,对于类UserAdAccount,它同时使用adAccountId和userId作为其复合主键。我需要将此复合主键用作索引的文档ID。

阅读《 Hibernate Search 5.11.5.Final:参考指南》(这是我正在使用的版本)后,我发现了以下内容: 功能更强大的TwoWayFieldBridge接口允许您将多个字段存储到索引中,这对于复合属性很有用,但实现起来较为复杂。

我不确定如何继续使用TwoWayFieldBridge在这里解决我的需求。任何帮助表示赞赏!

@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;
    }
}

1 个答案:

答案 0 :(得分:0)

来自the documentation

双向过程很重要,即: [...]

  • 对于TwoWayFieldBridge:对于给定的文档,get()返回的对象必须与最初传递给set()的对象相同。

此外,为了使TwoWayFieldBridge实现在文档标识符上使用时正确运行,void set(字符串名称,对象值,文档文档,LuceneOptions luceneOptions)方法必须遵循以下约定向文档添加字段:

  • 字段名称必须是name参数中提供的名称
  • 该字段值必须编码为字符串
  • 字段值必须与value参数的给定值唯一
  • 字段值必须与给定value参数的objectToString方法返回的值匹配。

您可以找到复合主键on github的示例实现:

> var.x[1].name
second
> var.x[1]["name"]
second

或者,如果您确定ID的组成部分不包含某个字符串,则可以将该字符串用作ID索引形式的分隔符,并且可以进行转换索引形式返回到原始ID。这意味着您可以使用更简单的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