根据索引检查实体的可搜索字段

Check searchable field of an entity based on indexing

我有一个定义如下的实体。

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

如果我在@Field上加上Index.NO(使实体字段不可搜索),比如把brandName的注解改成@Field(index = Index.NO),现在我只有两个可搜索字段:name 和 advertiserName,如果我们不考虑 id。在这种情况下,上面的示例查询将抛出运行时异常,因为它试图搜索不可搜索的 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

有一些限制,例如无法 "see" 自定义桥贡献的额外字段。但除此之外效果很好。