给出此域模型:
class User { // <- this is the root entity
@IndexedEmbedded
private Set<UserSkill> skills = new HashSet<>();
}
class UserSkill {
@IndexedEmbedded
private Skill skill;
@Enumerated
@Field(bridge = @FieldBridge(impl = EnumAsIntegerBridge.class))
private UserSkillLevel level;
}
class Skill {
@Field
private String name;
}
如何结合使用范围查询和术语查询来搜索具有给定级别特定技能的用户?
我尝试使用此查询来查找具有高级React技能的用户:
var q = new BooleanQuery.Builder();
q.add(queryBuilder.keyword().onField("skills.skill.name").matching("React").createQuery(), BooleanClause.Occur.MUST);
q.add(queryBuilder.range().onField("skills.level").above(UserSkillLevel.ADVANCED.ordinal()).createQuery(), BooleanClause.Occur.MUST);
var finalQuery = q.build();
返回的内容:
我希望它返回什么:
答案 0 :(得分:0)
在查询中,您从未提到两个约束(技能名称和技能级别)必须应用于同一技能。这就是为什么您得到此结果。
在Hibernate Search 5中,不支持这种“联接”。最好的办法是在单个字段(连接的字段)中索引技能名称和技能等级,但这有点麻烦。
在Hibernate Search 6中,对 nested 字段的支持可以解决此问题。但是,Hibernate Search 6的API却大不相同。
这是如何在Hibernate Search 6中实现所需的功能。
@Indexed
class User {
@IndexedEmbedded(storage = ObjectStorage.NESTED) // Notice this change
private Set<UserSkill> skills = new HashSet<>();
}
class UserSkill {
@IndexedEmbedded
private Skill skill;
@Enumerated
@GenericField(valueBridge = @ValueBridge(impl = EnumAsIntegerBridge.class)) // This changed too
private UserSkillLevel level;
}
class Skill {
@FullTextField(analyzer = "standard") // You will have to define this analyzer, see the getting started guide
private String name;
}
// New implementation of your bridge
class EnumAsIntegerValueBridge implements ValueBridge<Enum<?>, Integer> {
@Override
public Integer toIndexedValue(Enum<?> enum) {
return enum.ordinal();
}
}
然后查询:
List<User> hits = Search.session(entityManager).search(User.class)
.where(f -> f.nested().onField("skills").nest(f.bool()
.must(f.match().field("skills.skill.name").matching("React"))
.must(f.range().field("skills.level").atLeast(UserSkillLevel.ADVANCED))))
.fetchHits(20);
请注意,您将需要更新依赖项(groupId,artifactId和版本)。您可能想先看看getting started guide。