我将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);
}
答案 0 :(得分:0)
您只是没有映射字段userAdAccounts.id.userId
。您已映射字段userAdAccounts.id
,仅此而已。 Hibernate Search只会将AdAccount
类型的名为userAdAccounts.id
的字段添加到String
文档中。通常,Hibernate Search不会添加您不要求其添加的字段。
如果您还想为userId
添加一个单独的字段:
TwoWayFieldBridge
实现@IndexedEmbedded
添加到UserAdAccount.id
,并将@Field
添加到UserAdAccountId.userId
。