搜索
1.1 JPA配置
spring bean配置文件中
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
的jpaProperties属性集合增加如下配置:
    <prop key="hibernate.search.autoregister_listeners">true</prop>
    <prop key="hibernate.search.default.directory_provider">filesystem</prop>
    <prop key="hibernate.search.default.indexBase">lucene/indexes</prop>
    <prop key="hibernate.search.default_null_token">_null_</prop>
autoregister_listeners:自动注册监听器,即在hibernate监听到对象插入、更新、删除时自动更新对象索引__
directory_provider:可选值包括ram、filesystem等,具体可参考官方文档__
indexBase:对应上一项配置为filesystem,设定索引存放的根路径。__
default_null_token:默认空值标记,此项默认值即为_null_可以不用配置__
## 1.2 索引实体注解配置
### @Indexed
index属性指定索引名称(也对应于文件系统中目录名称),不指定默认类的全名。示例:
     @Indexed(index="requirement")
     public class Requirement extends Backlog {
     ...
     }
### @DocumentId
用于保证索引实体的唯一性。注解在主键上。采用JPA方式时,如果指定了@Id则不再需要标注该注解。
### @Field
index 指定是否索引,默认Index.YES
analyze 是否分析(分词器进行分词),默认Analyze.YES,目前对于不会搜索值的片段的字段都设置为了NO
store是否存储,默认Store.NO,设置为YES将占用索引空间,但支持投影,即直接从索引库得到字段值。
示例
    @Field(index = Index.YES, analyze = Analyze.NO, store = Store.YES)
    private String type;
    
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES)
    private String descr;
### @IndexedEmbedded  
对需要索引的关联对象采用此注解
    @IndexedEmbedded(indexNullAs = IndexedEmbedded.DEFAULT_NULL_TOKEN)
    private User assignee;
indexNullAs = IndexedEmbedded.DEFAULT_NULL_TOKEN,当关联对象是空时,存储为配置的null标记,默认不存储,根据实际需要配置此项(是否要根据空值进行查询)。
### @DateBridge
日期格式存储桥接转换
resolution = org.hibernate.search.annotations.Resolution.SECOND,存储到秒,可选:
     1) Resolution.DAY  
     2) Resolution.HOUR  
     3) Resolution.MILLISECOND  
     4) Resolution.MINUTE  
     5) Resolution.MONTH  
     6) Resolution.SECOND  
     7) Resolution.YEAR 
# 2.API
官方文档Example 1.9中一个完整的简单例子
    EntityManager em = entityManagerFactory.createEntityManager();
    FullTextEntityManager fullTextEntityManager =    org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
    em.getTransaction().begin();
    // create native Lucene query unsing the query DSL
    // alternatively you can write the Lucene query using the Lucene query parser
    // or the Lucene programmatic API. The Hibernate Search DSL is recommended though
    QueryBuilder qb = fullTextEntityManager.getSearchFactory()
        .buildQueryBuilder().forEntity( Book.class ).get();
    org.apache.lucene.search.Query query = qb
      .keyword()
      .onFields("title", "subtitle", "authors.name")
      .matching("Java rocks!")
      .createQuery();
    // wrap Lucene query in a javax.persistence.Query
    javax.persistence.Query persistenceQuery = 
        fullTextEntityManager.createFullTextQuery(query, Book.class);
    // execute search
    List result = persistenceQuery.getResultList();
    
    em.getTransaction().commit();
    em.close();
**需要注意的是搜索必须包含在一个事务内,比如搜索方法上需要有@Transactional的注解。**
## 2.1 Query API
###QueryBuilder
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
    		QueryBuilder qb =       fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(entityClass).get();
###关键字查询
    Query luceneQuery = qb.keyword().onField("descr").matching("搜索").createQuery();
keyword()方法意味着你正在尝试着去查询一个指定的词语。onField()方法指定查询哪个Lucene field。matching()方法告诉查询哪个词语。最后createQuery()方法创建Lucene query对象
###语句查询
Query luceneQuery = qb.phrase().onField("descr").matching("过滤器").createQuery();
目前主要使用此查询,因为使用keyword查询用目前默认标准分析器,查询“我们”与“们我”都会得到相同的结果
###通配符查询
    Query luceneQuery = qb.keyword().wildcard().onField("id").matching("*").createQuery();
用于返回全部记录
###范围查询
    TermRangeQuery query = new TermRangeQuery(field,20090101","20090105",true,true);  
最后两个参数分别为是否包含起始值,目前主要用于日期范围搜索。
###组合查询
    BooleanQuery boolQuery = new BooleanQuery();
    boolQuery.add(lucenequery,Occur.MUST);
    ...
SHOULD: query之间是或关系。
MUST:query之间是并关系。
MUST NOT:必须不包含该query。
###分页
    FullTextQuery ftQuery = fullTextEntityManager.createFullTextQuery(boolQuery, Backlog.class);
    ftQuery .setFirstResult(15); //从第几条记录开始  
    ftQuery .setMaxResults(10); //返回几条记录
###排序
ftQuery.setSort(new Sort(new SortField("updated", SortField.STRING, true)));
###返回结果
ftQuery.getResultList();
## 2.2 结果转换及排序特殊处理
### 结果转换
由于索引中存储关联对象时,只保存了键值,搜索结果返回前端时需要转换为相应对象,故利用hibernate提供的ResultTransformer接口进行扩展,定义了BacklogSearchResultTransformer接口及相应实现类HtmlResultTransformerImpl(已弃用)及ObjectResultTransformerImpl进行搜索结果的逐项转换。
使用示例如下:
        FullTextQuery ftQuery = fullTextEntityManager.createFullTextQuery(andQuery, entityClass);
        if (resultTransformer != null) {
            ftQuery.setResultTransformer(resultTransformer);
        }
在调用getResultList()时会调用转换类相应方法进行转换。另外需要注意的是接口使用之间要调用接口的initDictTranslateMap方法进行初始化数据的准备,并且是每次调用前都要执行。
###排序
同样由于索引中存储关联对象只保存了键值,如果按相应关联对象进行排序时,如果不进行处理则实际上是按相应的键值(id)进行排序而不是根据相应的名称,因此在LuceneSortFieldFactory的基础上扩展了BacklogSortFieldFactory进行了相应排序字段的排序处理。
使用示例如下:
        Sort sort = new Sort(sortFieldFactory.createSortField(pageAndSort.getSortField(), pageAndSort.isDesc()));
        ftQuery.setSort(sort);
 
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号