嵌入式组合主键上的休眠搜索

时间:2020-08-03 22:47:27

标签: hibernate-search

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

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

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

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

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

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

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

因此,就我而言,我做了以下工作。我可能应该用对象类型注册id并将USER_ID_SUFFIX更改为.userId和 AD_ACCOUNT_ID_SUFFIX到.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);
}

1 个答案:

答案 0 :(得分:0)

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

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

  • 使用我在answer to your other question中提到的TwoWayFieldBridge实现
  • @IndexedEmbedded添加到UserAdAccount.id,并将@Field添加到UserAdAccountId.userId