hibernate search初探1

hibernate提供了全文索引功能,非常棒,這裏簡要介紹下它的用法,
1. 在pom.xml引入包依賴

<dependency>
           <groupId>org.hibernate</groupId>
           <artifactId>hibernate-search-orm</artifactId>
           <version>${hibernate-search.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-smartcn</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-phonetic</artifactId>
            <version>${lucene.version}</version>
        </dependency>
  1. hibernate配置 search index保存路徑
 <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
        destroy-method="destroy">
        <property name="dataSource" ref="poolingDataSource" />
        <property name="configLocation">
            <value> classpath:hibernate.cfg.xml </value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <!-- Booleans can be easily used in expressions by 
                     declaring HQL query substitutions in Hibernate configuration -->
                <prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
                <!-- http://ehcache.org/documentation/integrations/hibernate -->
                <!-- http://www.tutorialspoint.com/hibernate/hibernate_caching.htm -->
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <!-- org.hibernate.cache.ehcache.EhCacheRegionFactory -->
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <!-- hibernate只會緩存使用load()方法獲得的單個持久化對象,如果想緩存使用findall()、 list()、Iterator()、createCriteria()、createQuery()
                                等方法獲得的數據結果集的話,就需要設置hibernate.cache.use_query_cache true  -->
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
                <!-- Hibernate Search index directory -->
                ***<prop key="hibernate.search.default.indexBase">indexes/</prop>*** 
            </props>
        </property>
    </bean> 
  1. 對需要搜索的類加上Indexed Annotation,然後對類中可以被搜索的字段加上@Field Annotation,通常Enum字段不需要Analyzer進行詞法分析,其他字段則需要,對於不需要Projection(返回部分字段)的情況下,不需要在index中存儲實際數據。可以通過AnalyzerDef來定義不同的詞法分析器以及對於的特殊詞過濾器
@Indexed
@AnalyzerDef(
        name="enTopicAnalyzer",
        charFilters={
            @CharFilterDef(factory=HTMLStripCharFilterFactory.class)
        },
        tokenizer=@TokenizerDef(factory=StandardTokenizerFactory.class),
        filters={
            @TokenFilterDef(factory=StandardFilterFactory.class),
            @TokenFilterDef(factory=StopFilterFactory.class),
            @TokenFilterDef(factory=PhoneticFilterFactory.class,
                params = {
                    @Parameter(name="encoder", value="DoubleMetaphone")
                }),
            @TokenFilterDef(factory=SnowballPorterFilterFactory.class,
                params = {
                    @Parameter(name="language", value="English")
                })
            }
    )
public class Topic {

    ......
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
    @Analyzer(definition = "enTopicAnalyzer")
    private String title;
    ......
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
    @Analyzer(definition = "enTopicAnalyzer")
    private String content;
    ......    
    @Enumerated(EnumType.STRING)
    @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO, bridge=@FieldBridge(impl=EnumBridge.class))
    private TopicStatus status;
    ...
    }
  1. 通過代碼對已有數據創建index
ApplicationContext context = new ClassPathXmlApplicationContext("spring-resources.xml");

        SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");

        Session sess = sessionFactory.openSession();
        FullTextSession fullTextSession = Search.getFullTextSession(sess);
        try {
            fullTextSession.createIndexer().startAndWait();
        } catch (InterruptedException e) {
             LOG.error(e.getMessage(), e);
        } finally {
            fullTextSession.close();
        }
        ((AbstractApplicationContext)context).close();
  1. 創建查詢fulltextsession,按照query條件獲取結果
 FullTextSession fullTextSession = Search
                .getFullTextSession(getSession());

        QueryBuilder queryBuilder = fullTextSession.getSearchFactory()
                .buildQueryBuilder().forEntity(Show.class).get();
        org.apache.lucene.search.Query luceneQuery = null;

            luceneQuery = queryBuilder.keyword()// .wildcard()
                    .onFields("title", "content").matching(query.getKeyword())
                    // .matching("*" + query.getKeyword() + "*")
                    .createQuery();

        FullTextQuery hibernateQuery = fullTextSession.createFullTextQuery(
                luceneQuery, Show.class);
        return hibernateQuery.list();

note:
1. 在一次測試過程中,修改了value object,添加了新的index,忘記了rebuildIndex,結果unit test沒問題,生成環境就出錯了。
2. 搜索還不是很強大,比如搜索測,含有測試的結果可能就搜索不出來

發佈了110 篇原創文章 · 獲贊 14 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章