天天看點

Compass2.2 學習筆記

學習Compass是個很快速的過程,它不像其他架構需要花很多時間學習它的API和了解它的工作流程.似乎Compass就是兩個架構的組合版本.

為什麼這樣說呢?看下它的工作流程就知道了:

Compass2.2 學習筆記

這個結構和Hibernate很相像,無非就是Hibernate把JDBC封裝了一把.是以從結構上來說,隻要我們了解了Hibernate,就已經對Compass有了了解.那麼Hibernate需要提供API和配置檔案來對JDBC進行操作,那麼Compass呢?Compass不僅從結構上模仿了Hibernate,就連API風格也不盡相同.我們把它和Hibernate的API做個對比就知道了:

再把兩個session的核心方法比較一下:

Hibernate session API

CompassSession API

save(Object)

create(Object)

建立索引

saveOrUpdate(Object)

儲存或更新

delete(Object)

delete(Class, ids...)

删除索引

get()

擷取

createQuery(hql).list()

find(String)

使用查詢字元串查詢

是以說,Compass與Hibernate極為相似,Compass總結起來就兩句話:

Hibernate的風格

Lucene的思想

Compass2.2的版本所用的Lucene2.4.1,Lucene2.4與目前的Lucene3.0相比:

API的差别很大,代碼不能通用

3.0效率更高

但是Compass用起來舒服,學習成本不高,是以這裡用Compass2.2對索引庫進行操作.

所需jar包

Compass2.2 學習筆記

Compass配置檔案

先從Compass的文檔中複制配置模闆:

再對其進行詳細配置:

在Lucene裡面,如果将對象的資料存儲在索引庫裡面,需要先把對象轉換為Document,這個工作在Compass裡面會自動将其轉為Document,在Lucene裡面還需要指定哪些Field是可以搜尋的,并且是否存儲在緩存資料裡面,那麼Compass也要提供相應的配置才行,Compass如何做到呢?它會在主配置檔案(compass.cfg.xml)中通過反射得到Class,得到該類上所有的注解資訊,這就是映射資訊的作用.用Article作為測試類,屬性如下:

再生成對應的getter、setter方法,我們要指明這個類的資料是可以被搜尋到的,需要在類上添加注解:

這就表明這是一個可搜尋對象,Compass會通過反射創造出該類的執行個體,是以一定要有無參的構造函數,并且有删除索引的需求,還有Field的配置等,對可搜尋對象的所有要求為:

要有預設的構造方法

在類上要有:@Searchable

要有一個唯一辨別符的屬性:@SearchableId

其他的屬性用:@SearchableProperty

第二個條件主要是針對删除和更新的,因為之前對Compass的核心方法和Hibernate的核心方法進行了對比,删除索引是用delete()方法,delete()方法不是接收一個對象,因為你把對象給它,它也不知道對象與與對象之間是以什麼為差別的,是以給它一個Class,它通過在主配置檔案中的映射資訊,反射出該類, 再用你提供的第二個參數,也就是唯一辨別符,來找到索引,進而進行删除和更新的操作,這就是@SearchableId的作用.

在Lucene裡面将對象轉為Document對象的時候,需要儲存的資料用Field對象來封裝,封裝的時候,要提供是否存儲資料以及是否為資料建立索引等配置,這就是@SearchableProperty的作用.完整的對類的配置為下,以id作為唯一辨別符:

注意導包不要導錯了,全是org.compass.annotations包中的.屬性配置基本和Lucene裡面一樣.唯一需要注意的就是對數字的處理.如果在Compass的使用過程中出來問題,或者找不到索引之類的,一定要記得看你的資料類型.

建立索引的方式基本與Lucene相同,畢竟Compass是對Lucene的封裝,思想是屬于Lucene的.就像Hibernate使用Session需要先得到SessionFactory一樣,Compass也需要獲得SessionFactory,并且也是由Configuration對象來取得的:

在Hibernate中,對于Session,SessionFactory隻需要一個就夠了,對于一個索引庫,全局隻有一個Compass對象就可以了:

簡單的查詢,就像Lucene的查詢字元串一樣.

這隻是一個簡單增加索引和查詢索引的例子,權當做Hello World吧.

每次使用Session都要從SessionFactory中擷取,無疑是很麻煩的,不如把SessionFactory維護在工具類裡面,全局隻有一個,在用一個靜态方法得到一個Session.

注意,如果唯一辨別符是數字,并且沒有在實體類裡面對唯一辨別符使用format屬性,則以上代碼擷取不到!

預設的分詞是标準分詞器,這個分詞器對中文采取的是單字分詞,根本沒辦法使用.一般做法是用第三方的分詞器,常用的有極易分詞、庖丁分詞、IKAnalyzer等.要使用分詞器,需要在Compass的主配置檔案裡面進行配置,這裡采用極易分詞:

這個分詞器對中文支援比較好,采用的是詞庫分詞,準确度較高.

接下來還要配置高亮器,配置高亮器主要有三點:字首、字尾、高亮顯示的摘要.同樣是在主配置檔案裡面進行配置:

注意,字首和字尾中的标簽,要轉義,不然會和配置檔案中的符号産生沖突!

一般來說搜尋結果的排序和Lucene裡面是一樣的,按照相關度得分進行排序,在實際應用中,往往需要人工操縱得分,比如給了推廣費之類的,既然有這種需求,自然就有這種做法,和Lucene的不同之處在于,Lucene在添加索引時控制相關度得分的比重,Compass也是在添加索引時控制,不過需要在實體類裡面增加一個屬性和它的getter、setter方法,這個屬性決定了所有這個類的資料的相關度得分的比重,也就是說可以讓隻要是這個實體類的資料,就能比别的類的資料得分要高,并且隻要是設定了這個屬性,就能在添加索引時控制相關度得分的比重:

在實體裡面增加這個屬性,屬性名無所謂,類型是float,最重要的是要有getter、setter方法和@SearchableBoostProperty,必須要有這處注解,Lucene才能在你調用相關方法的時候,通過反射獲得有這個注解的屬性名,在調用它的getter方法,得到值,那麼在程式中就要增加一句代碼:

其他地方都是一樣的.除了對相關度得分的排序以外,還可能在搜尋時使用某個屬性的值進行排序.這也是可以的:

隻需要在得到搜尋結果之前做一點改動.先得到CompassQuery對象,調用這個對象的addSort()方法增加排序規則.像上述一樣,則是按升序進行排序,也可以替換成下面這句使用降序排列:

注意,指定參與排序的字段時,參與排序的字段必須要是Index.NOT_ANALYZED,否則分詞後無法找到!

有時候也會使用到過濾器對搜尋結果進行過濾.

但是使用過濾器是效率很低的做法,使用查詢字元串可以獲得更高的效率,而且可以達到同樣的效果.下面就對各種查詢進行簡要說明:

基本上還是Lucene的那一套,隻是簡單的封裝一下而已.

如果本文有任何問題,請及時指出,以免對後來者産生不必要的困擾,不勝感激!