我有一个实体定义如下。
public class Deal {
@Id
@DocumentId
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Field
@Column(name = "NAME")
private String name;
@Field
@Column(name = "ADVERTISER_NAME")
private String advertiserName;
@Field
@Column(name = "BRAND_NAME")
private String brandName;
//other fields and getters/setters omitted for brevity
}
如果我想搜索所有可搜索的字段,我可以执行以下操作,它演示了onField,onFields和andFields的用法。
Query luceneQuery1 = mythQB
.simpleQueryString()
.onFields("name", "history", "description")
.matching("teststring")
.createQuery();
Query luceneQuery2 = mythQB
.simpleQueryString()
.onField("name")
.boostedTo(5f)
.andFields("advertiserName", "brandName")
.boostedTo(2f)
.withAndAsDefaultOperator()
.matching("teststring")
.createQuery();
如果我将Index.NO添加到@Field(使实体字段无法搜索),例如,将brandName的注释更改为@Field(index = Index.NO),现在我只有两个可搜索的字段:name和advertiserName,if我们不考虑身份证。在这种情况下,上面的示例查询将抛出运行时异常,因为它尝试搜索不可搜索的brandName。
我尝试过类似下面的内容,根据字段是否有注释动态获取可搜索字段的完整列表。但如果索引是Index.NO,这将不起作用。
我的问题是,有没有办法根据实际索引值动态获取可搜索字段的完整列表?
protected String[] getSearchableFields() {
List<String> fields = Lists.newArrayList();
Class<?> c = clazz;
while (c != null) {
for (Field field : c.getDeclaredFields()) {
if (field.isAnnotationPresent(org.hibernate.search.annotations.Field.class)
|| field.isAnnotationPresent(org.hibernate.search.annotations.Fields.class)) {
if (field.getType().isAssignableFrom(String.class)) {
fields.add(field.getName());
}
}
}
c = c.getSuperclass();
}
return fields.toArray(new String[fields.size()]);
}
Hibernate Search中有一个元数据API。
FullTextSession ftSession = ...;
IndexedTypeDescriptor indexedType = ftSession.getSessionFactory().getIndexedTypeDescriptor(clazz);
for (PropertyDescriptor property : indexedType.getIndexedProperties()) {
for (FieldDescriptor field : property.getIndexedFields()) {
if (field.getIndex() == Index.YES) {
// do something
}
}
}
有关更多信息,请参阅this section of the reference documentation。
有一些限制,例如无法“查看”自定义网桥提供的额外字段。但除此之外,它的效果很好。