嵌入式组合主键上的休眠搜索 [英] Hibernate search on embedded composite primary key

查看:68
本文介绍了嵌入式组合主键上的休眠搜索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将UserAdAccountId类定义为嵌入式ID类.使用这个id类,我定义了类UserAdAccount,并对复合主键使用了双向字符串字段桥.然后,我尝试对Entity类AdAccount进行休眠搜索,但遇到了以下异常:无法在AdAccount中找到字段userAdAccounts.id.userId.

I have class UserAdAccountId defined as an embedded id class. Using this id class, I defined class UserAdAccount and used a two way string field bridge for the composite primary key. Then, I tried to do a hibernate search on the Entity class AdAccount, but ran into this exception: Unable to find field userAdAccounts.id.userId in AdAccount.

如您所见,我通过了"userAdAccounts.id.userId"作为onField()的字段路径,因为userAdAccounts是一组UserAdAccount. UserAdAccount的ID为UserAdAccountId类型,其字段分别为userId和adAccountId.我使用@IndexedEmbedded(includeEmbeddedObjectId = true)来确保此UserAdAccountId类型的ID包含在索引中.

As you can see, I passed "userAdAccounts.id.userId" as the field path to onField() because userAdAccounts is a set of UserAdAccount. UserAdAccount's id is of type UserAdAccountId, which has both userId and adAccountId as its fields. I used @IndexedEmbedded(includeEmbeddedObjectId = true) to ensure that this id of type UserAdAccountId is included in indexing.

我的问题是,为什么我仍然看到此错误的字段路径错误?

My question is that why I am still seeing this incorrect field path error?

@Indexed
@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = {"userId", "adAccountId"})
@ToString
public class UserAdAccountId implements Serializable {

    @Column(name = "USER_ID")
    @GenericGenerator( name = "native", strategy = "native")
    @Field
    private Long userId;

    @Column(name = "AD_ACCOUNT_ID")
    @GenericGenerator( name = "native", strategy = "native")
    @Field
    private Long adAccountId;

}

@Entity (name = "JHI_USER_AD_ACCOUNT")
@Indexed
@Getter
@Setter
public class UserAdAccount implements SearchableEntity, Serializable {

    @EmbeddedId
    @DocumentId
    @FieldBridge(impl = UserAdAccoutPrimaryKeyBridge.class)
    @IndexedEmbedded(includePaths = {"userId"})
    private UserAdAccountId id;

    @ManyToOne
    @JoinColumn(name = "USER_ID", referencedColumnName = "ID", updatable = false, insertable = false)
    private User user;

    @ManyToOne
    @JoinColumn(name = "AD_ACCOUNT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
    private AdAccount adAccount;

}

@Entity
@Indexed
@Table(name = "AD_ACCOUNT")
@Getter
@Setter
@ToString
public class AdAccount implements SearchableEntity, Serializable {
    @Id
    @DocumentId
    @SortableField
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO, generator="native")
    @GenericGenerator( name = "native", strategy = "native")
    private Long id;

    @IndexedEmbedded(includeEmbeddedObjectId = true)
    @OneToMany(mappedBy = "adAccount", fetch = FetchType.LAZY)
    private Set<UserAdAccount> userAdAccounts = new HashSet<>();
}

我实现的休眠搜索逻辑:

if(this.searchRequest.getExactMatchFilters().containsKey("userId")) {
    Set<String> userIds = this.searchRequest.getExactMatchFilters().get("userId");
    BooleanJunction<BooleanJunction> combined = queryBuilder.bool();
    combined.minimumShouldMatchNumber(1);
    for(String userId : userIds) {
        combined.should(queryBuilder.keyword().onField("userAdAccounts.id.userId").matching(userId).createQuery());
    }
    filters.add(combined.createQuery());
}

更新:关于双向字段桥接的动态映射错误.我在官方文档中找到了这个:在官方文档中找到了这个:

Update: About the dynamic mapping error with the two way field bridge. I found this on the official documentation: I found this on the official documentation:

当您的MetadataProvidingFieldBridge注册一个名称为现有字段名称的字段,并附加一个点和另一个字符串(如名称+".mySubField")时,Hibernate Search会将其转换为具有mySubField属性的对象. JSON文档已发送到Elasticsearch.

When your MetadataProvidingFieldBridge registers a field whose name is the name of an existing field, with a dot and another string appended, like name + ".mySubField", Hibernate Search will translate it as an object with a property mySubField in the JSON document sent to Elasticsearch.

因此,子字段只能具有OBJECT类型的父字段:显然,Elasticsearch将拒绝具有mySubField属性的String或Integer.因此,每次注册名为foo.bar的字段时,都必须使用OBJECT类型注册其父字段foo,如以下示例所示.否则,Hibernate Search生成Elasticsearch架构时会导致错误.

As a result, sub-fields can only have a parent field with the OBJECT type: obviously, Elasticsearch would reject a String or an Integer with mySubField property. So every time a field named foo.bar is registered, its parent field foo must be registered with the OBJECT type, as in the following example. Not doing so will result in errors when Hibernate Search generates the Elasticsearch schema.

因此,就我而言,我执行了以下操作.我可能应该用对象类型注册id并将USER_ID_SUFFIX更改为.userId和 AD_ACCOUNT_ID_SUFFIX到.adaccountId?

So in my case, I did the following. I should probably register id with Object type and also change USER_ID_SUFFIX to be .userId and AD_ACCOUNT_ID_SUFFIX to .adaccountId?

private static final String USER_ID_SUFFIX = "_userId";
private static final String AD_ACCOUNT_ID_SUFFIX = "_adaccountId";

@Override
public void configureFieldMetadata(String id, FieldMetadataBuilder builder) {
    builder.field(id + USER_ID_SUFFIX, FieldType.LONG)
            .field(id + AD_ACCOUNT_ID_SUFFIX, FieldType.LONG);
}

推荐答案

您只是没有映射字段userAdAccounts.id.userId.您已映射字段userAdAccounts.id,仅此而已. Hibernate Search只会将userAdAccounts.id类型的userAdAccounts.id字段添加到AdAccount文档中.通常,Hibernate Search不会添加您不要求其添加的字段.

You simply did not map field userAdAccounts.id.userId. You mapped field userAdAccounts.id, and that's about it. Hibernate Search will only ever add to AdAccount documents a field named userAdAccounts.id of type String. Hibernate Search, as a rule, does not add fields that you didn't ask it to add.

如果您还想为userId添加单独的字段:

If you also want to add a separate field for the userId:

  • Either use the TwoWayFieldBridge implementation that I mentioned in my answer to your other question
  • Or add @IndexedEmbedded to UserAdAccount.id and @Field to UserAdAccountId.userId.

这篇关于嵌入式组合主键上的休眠搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆