- 我們在使用lucene管理document時,難免有些復雜,并且在做增量索引的時候會比較繁瑣,現介紹compass如下:??
- compass對lucene的使用就如同Hibernate和對jdbc的使用。??
- Compass的使用步驟:??
- Hibernate的實現步驟是:??
- 1 》??設計實體??
- 2 》??配置映射元數據?(xml?/?注解—Hibernate3才推出來的)??
- 3 》??利用Hibernate的api完成對實體的CURD??
- 我們目前使用compass的操作步驟就與Hibernate的基本一樣的:??
- Hibernate的第二步是映射到數據庫,而compass是映射到收索引擎里面去。??
- 1 》??設計收索實體?–?就?是一個普通的javabean??
- 你要寫這么一個實體,定義一些屬性,好比產品的id、名稱??
- 2 》??配置映射元數據?–?針對收索引擎映射-我們采用主注解的方式??
- 我們使用 @Searchable ?標注映射為收索實體,映射到Lucene中的document??
- 假設是采用注解的形式,我們就需要在實體和屬性上面加上一些注解??
- @Entity ?(映射到數據庫中的表)???
- @Searchable ??–>?這個注解把該類聲明為搜索實體,映射到lucene中的document??
- Public? class ?Product{??
- ??????????? @Id ?(Hibernate用來表示實體的標識屬性)??
- ??????????? @SearchableId ?(compass標注為標識屬性)??
- ???????????Private?Integer?id;??
- ??????????? @Column ()??
- ??????????? @SearchableProperty ??à??映射搜索屬性??
- ???????????Private?String?name;??
- }??
- ???
- 3 >利用compass?api完成對實體的添/刪/查操作??
- ??hibernate.cfg.xml?/?compass.cfg.xml?放在類路徑下??
- hibernate:?SessionFactory?sessionFactory?=? new ?Configuration().configure().buildSessionFactory();??
- Compass:???Compass?compass?=? new ?CompassConfiguration().configure().buildCompass();??
- ??SessionFactory?==?Compass???
- ???
- hibernate:?Session?session?=?sessionFactory.openSession();??
- compass:???CompassSession?session?=?compass.openSession();??
- ???????????Session?=?CompassSession??
- ???
- Hibernate:??session.beginTransaction();??
- compass:????session.beginTransaction();??
- ???
- Hibernate:??session.save(product)/persist();??
- compass:????session.save(product)/create();??
- ???
- Hibernate:??session.getTransaction().commit();??
- compass:????session.getTransaction().commit();??
- ???
- ??session.close();??
- ??sessionFactory.close();??
- ???
- ?????????學習一下compass映射注解:常用的就 5 個??
- ????????? @Searchable ? //告訴compass,將該類映射到lucene的Document ??
- ?????????注意注解如果標注在屬性上只能標注在get方法上面??
- ????????? @SearchableId ? //compass要求每個搜索實體類都要具有一個標識屬性,這點和Hibernate相似 ??
- ????????? @SearchableProperty (index=Index.NOT_ANALYZED?,store=Store.YES) //?store的默認值為Store.YES ??
- 類別id不需要分詞,蛋需要索引并存儲??
- Index。UN_TOKENIZED?不對該field進行分詞,但是要索引,該屬性已過時,建議產用NOT__ANALYZED替換??
- Index.TOKENIZED:先分詞后索引。該屬性已過時,建議采用ANALYZED替換??
- Inde.NOT_ANALYZED?不分詞,但建立索引??
- Index.ANALYZED?分詞并且建立索引??
- ???
- @SearchableId ?Property(boost= 2 ) //boost的默認值為1,用戶設置屬性在索引中的重要性 ??
- 如下:??
- @Searchable ? //告訴compass,將該類映射到Lucene的Document ??
- public ? class ?Product?{??
- ????????? private ?Integer?id;??
- ????????? private ?String?name;??
- ????????? private ?String?content;??
- ????????? private ?Float?price;??
- ????????? private ?String?note;??
- ????????? private ?Integer?position;??
- ????????? private ?Integer?typeid;??
- ???????????
- ????????? public ?Product(){}??
- ???????????
- ????????? public ?Product(Integer?id)?{??
- ??????????????????? this .id?=?id;??
- ?????????}??
- ???
- ????????? public ?Product(Integer?id,?String?name,?String?content,?Float?price,String?note,Integer?typeid,Integer?position)?{??
- ??????????????????? this .id?=?id;??
- ??????????????????? this .name?=?name;??
- ??????????????????? this .content?=?content;??
- ??????????????????? this .price?=?price;??
- ??????????????????? this .note?=?note;??
- ??????????????????? this .typeid?=?typeid;??
- ??????????????????? this .position?=?position;??
- ?????????}??
- ???????????
- ????????? @SearchableId ? //compass要求每個搜索實體類都要具有一個標識屬性,這點和Hibernate相似 ??
- ????????? public ?Integer?getId()?{??
- ??????????????????? return ?id;??
- ?????????}??
- ????????? public ? void ?setId(Integer?id)?{??
- ??????????????????? this .id?=?id;??
- ?????????}??
- ????????? //類別id不需要分詞,但需要索引并儲存 ??
- ????????? //Index.UN_TOKENIZED:不對該Field進行分詞,但是要索引.該屬性已過時,建議采用NOT_ANALYZED替換 ??
- ???? //Index.TOKENIZED:先分詞后索引。該屬性已過時,建議采用ANALYZED替換 ??
- ????????? //Index.NOT_ANALYZED:不分詞,但建立索引 ??
- ????????? //Index.ANALYZED?:分詞并且建立索引 ??
- ???????????
- ????????? @SearchableComponent ? //關聯的符合索引,專門用來標注復合類型 ??
- ?????????那么被標注的這個屬性對應的類,我們也要標注一下為收索實體,但是這個搜索實體他不是單獨存在的,他只是最為產品搜索實體的一部分??
- @Searchable (root= false )??
- @SearchableProperty (index=Index.NO?,store=Store.YES)??
- ?????????我們對他的主鍵不需要索引只需要存儲??
- ?????????當你存在雙向關系的時候,并且需要引用會對應的實體,反指引用??
- ????????? @SearchableReference ??
- ???
- @SearchableProperty (index=Index.NOT_ANALYZED,?store=Store.YES) //store的默認值為Store.YES ??
- ????????? public ?Integer?getTypeid()?{??
- ??????????????????? return ?typeid;??
- ?????????}??
- ???
- ????????? public ? void ?setTypeid(Integer?typeid)?{??
- ??????????????????? this .typeid?=?typeid;??
- ?????????}??
- ???
- ????????? @SearchableProperty (boost= 2 ) //boost的默認值為1,用于設置屬性在索引中的重要性 ??
- ????????? public ?String?getName()?{??
- ??????????????????? return ?name;??
- ?????????}??
- ????????? public ? void ?setName(String?name)?{??
- ??????????????????? this .name?=?name;??
- ?????????}??
- ???
- ????????? @SearchableProperty ??
- ????????? public ?String?getContent()?{??
- ??????????????????? return ?content;??
- ?????????}??
- ????????? public ? void ?setContent(String?content)?{??
- ??????????????????? this .content?=?content;??
- ?????????}??
- ????????? //價格不需要進行搜索,但需要存儲,如果沒有存儲,就需要從數據庫中獲取價格了 ??
- ????????? @SearchableProperty (index=Index.NO) //store的默認值為Store.YES ??
- ????????? public ?Float?getPrice()?{??
- ??????????????????? return ?price;??
- ?????????}??
- ????????? public ? void ?setPrice(Float?price)?{??
- ??????????????????? this .price?=?price;??
- ?????????}??
- ????????? @SearchableProperty (store=Store.YES)??
- ????????? public ?String?getNote()?{??
- ??????????????????? return ?note;??
- ?????????}??
- ???
- ????????? public ? void ?setNote(String?note)?{??
- ??????????????????? this .note?=?note;??
- ?????????}??
- ????????? @SearchableProperty (index=Index.NOT_ANALYZED,?store=Store.YES) //store的默認值為Store.YES ??
- ????????? public ?Integer?getPosition()?{??
- ??????????????????? return ?position;??
- ?????????}??
- ???
- ????????? public ? void ?setPosition(Integer?position)?{??
- ??????????????????? this .position?=?position;??
- ?????????}??
- ???????????
- ???????????
- }??
- ???
- ???
- 我們不集成spring的編程配置和使用方式如下:??
- import ?java.util.ArrayList;??
- import ?java.util.List;??
- ???
- import ?org.compass.annotations.config.CompassAnnotationsConfiguration;??
- import ?org.compass.core.Compass;??
- import ?org.compass.core.CompassException;??
- import ?org.compass.core.CompassHits;??
- import ?org.compass.core.CompassQueryBuilder;??
- import ?org.compass.core.CompassSession;??
- import ?org.compass.core.CompassTransaction;??
- import ?org.compass.core.CompassQuery.SortDirection;??
- import ?org.compass.core.CompassQuery.SortPropertyType;??
- import ?org.compass.core.config.CompassEnvironment;??
- ???
- import ?cn.itcast.bean.Product;??
- import ?cn.itcast.bean.QueryResult;??
- import ?cn.itcast.compass.service.ProductSearch;??
- ???
- public ? class ?ProductSearchBean? implements ?ProductSearch?{??
- ????????? private ?Compass?compass?=? null ; //-->SessionFactory ??
- ???????????
- ????????? public ?ProductSearchBean(){??
- ???????????????????? try ?{??
- ????????????????????????????? //編程式配置 ??
- ????????????????????????????compass?=? new ?CompassAnnotationsConfiguration()??
- ????????????????????????????.setSetting(CompassEnvironment.CONNECTION,? "[url=file://indexfile]file://indexfile[/url]" )??
- ???????????????????????????? //.setSetting(CompassEnvironment.CONNECTION,?"ram://index")//在內存中建立索引 ??
- ????????????????????????????.setSetting( "compass.engine.highlighter.default.formatter.simple.pre" , "<font?color='red'>" )??
- ????????????????????????????.setSetting( "compass.engine.highlighter.default.formatter.simple.post" , "</font>" )??
- ????????????????????????????.addScan( "cn.itcast.bean" ).buildCompass();??
- ???????????????????}? catch ?(Exception?e)?{??
- ????????????????????????????e.printStackTrace();??
- ???????????????????}??
- ?????????}??
- ???????????
- ????????? //compass支持增量索引,社會上很多公司,他們的產品都沒有實現增量索引,1>lucene版本比較低,不支持增量索引,2>要增量索引,技術要求稍微有點高 ??
- ????????? //(晚上?2-3,定時器,把索引文件刪除,重新生成索引)實時性不強,在索引文件更新的時候,用戶是訪問不了的 ??
- ????????? public ? void ?buildIndex(){??
- ???????????????????CompassSession?session?=? null ;??
- ???????????????????CompassTransaction?tx?=? null ;??
- ??????????????????? try ?{??
- ????????????????????????????session?=?compass.openSession();??
- ????????????????????????????tx?=?session.beginTransaction();????????
- ????????????????????????????Product?p1?=? new ?Product( 12 , "c瑜珈球" , "非常好的瑜珈球" ,12f,? "www" ,? 2 ,? 12 );??
- ????????????????????????????session.create(p1);??
- ????????????????????????????Product?p2?=? new ?Product( 35 , "b瑜珈球" , "天花板瑜珈球,good" ,42f,? "mmm" , 2 , 9 );??
- ????????????????????????????session.create(p2);??
- ????????????????????????????Product?p3?=? new ?Product( 8 , "a藍球瑜珈球" , "藍球小子" ,125f,? "ppp" , 5 , 8 );?????????????????????????????
- ????????????????????????????session.create(p3);??
- ????????????????????????????tx.commit();??
- ???????????????????}? catch ?(CompassException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????????tx.rollback();??
- ???????????????????} finally {??
- ???????????????????????????? if (session!= null ?&&?!session.isClosed())?session.close();??
- ???????????????????}??
- ?????????}??
- ???
- ????????? public ? void ?deleteIndex(Product?product)?{??
- ???????????????????CompassSession?session?=? null ;??
- ???????????????????CompassTransaction?tx?=? null ;??
- ??????????????????? try ?{??
- ????????????????????????????session?=?compass.openSession();??
- ????????????????????????????tx?=?session.beginTransaction();??
- ???????????????????????session.delete(product);??
- ???????????????????????tx.commit();??
- ???????????????????}? catch ?(CompassException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????????tx.rollback();??
- ???????????????????} finally {??
- ???????????????????????????? if (session!= null ?&&?!session.isClosed())?session.close();??
- ???????????????????}??
- ?????????}??
- ???
- ????????? public ? void ?updateIndex(Product?product)?{??
- ???????????????????CompassSession?session?=? null ;??
- ???????????????????CompassTransaction?tx?=? null ;??
- ??????????????????? try ?{??
- ??????????????????????session?=?compass.openSession();??
- ??????????????????????tx?=?session.beginTransaction();??
- ??????????????????????session.delete(product);??
- ??????????????????????session.save(product);??
- ??????????????????????tx.commit();??
- ???????????????????}? catch ?(CompassException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????????tx.rollback();??
- ???????????????????} finally {??
- ???????????????????????????? if (session!= null ?&&?!session.isClosed())?session.close();??
- ???????????????????}??
- ?????????}??
- ???
- ????????? public ? void ?destroy(){??
- ???????????????????compass.close();??
- ?????????}??
- ???????????
- ????????? public ?QueryResult<Product>?search(String?keyword,? int ?firstIndex,? int ?maxResult)?{??
- ???????????????????QueryResult<Product>?qr?=? new ?QueryResult<Product>();??
- ???????????????????CompassSession?session?=? null ;??
- ???????????????????CompassTransaction?tx?=? null ;??
- ??????????????????? try ?{??
- ?????????????????????????????session?=?compass.openSession();??
- ?????????????????????????????tx?=?session.beginTransaction();??
- ???????????????????????????? //對所有索引Field進行搜索,你也可以指定對某個Field搜索,如:"name:jack",如果想指定多個字段可以用空格和"+"隔開如"name:jack?+content:xxx" ??
- ?????????????????????????????CompassHits?hits?=?session.find(keyword);?????????????
- ?????????????????????????????List<Product>?products?=? new ?ArrayList<Product>();??
- ????????????????????????????? int ?length?=?firstIndex+?maxResult;??
- ????????????????????????????? if (length>hits.length())?length?=?hits.length();????????????????????????????
- ????????????????????????????? for ( int ?i=firstIndex;?i<length;?i++){??
- ??????????????????????????????????????Product?product?=?(Product)hits.data(i);??
- ??????????????????????????????????????product.setContent(hits.highlighter(i).fragment( "content" ));??
- ??????????????????????????????????????products.add(product);??
- ?????????????????????????????}??
- ?????????????????????????????qr.setResultlist(products);??
- ?????????????????????????????qr.setTotalrecord(hits.length());??
- ?????????????????????????????hits.close();??
- ???????????????????}? catch ?(CompassException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????????tx.rollback();??
- ???????????????????} finally {??
- ???????????????????????????? if (session!= null ?&&?!session.isClosed())?session.close();??
- ???????????????????}??
- ??????????????????? return ?qr;??
- ?????????}??
- ???????????
- ????????? public ?QueryResult<Product>?search(String?keyword,?Integer?typeid,? int ?firstIndex,? int ?maxResult)?{??
- ???????????????????QueryResult<Product>?qr?=? new ?QueryResult<Product>();??
- ???????????????????CompassSession?session?=? null ;??
- ???????????????????CompassTransaction?tx?=? null ;??
- ??????????????????? try ?{??
- ?????????????????????????????session?=?compass.openSession();??
- ?????????????????????????????tx?=?session.beginTransaction();??
- ????????????????????????????? //查詢指定類別的匹配記錄,并按position降序排序 ??
- ?????????????????????????????CompassQueryBuilder?queryBuilder?=?session.queryBuilder();??
- ?????????????????????????????CompassHits?hits?=?queryBuilder.bool()??
- ????????????????????????????????????.addMust(queryBuilder.spanEq( "typeid" ,?typeid))??
- ????????????????????????????????????.addMust(queryBuilder.queryString(keyword).toQuery())??
- ??????????????????????????????????.toQuery().addSort( "position" ,?SortPropertyType.FLOAT,?SortDirection.REVERSE)??
- ??????????????????????????????????.hits(); //sql:?typeid=1?and?(xxxx?like??)?order?by?positoin?desc ??
- ???????????????????????????????
- ?????????????????????????????List<Product>?products?=? new ?ArrayList<Product>();??
- ????????????????????????????? int ?length?=?firstIndex+?maxResult;??
- ????????????????????????????? if (length>hits.length())?length?=?hits.length();????????????????????????????
- ????????????????????????????? for ( int ?i=firstIndex;?i<length;?i++){??
- ??????????????????????????????????????Product?product?=?(Product)hits.data(i);??
- ??????????????????????????????????????product.setContent(hits.highlighter(i).fragment( "content" ));??
- ??????????????????????????????????????products.add(product);??
- ?????????????????????????????}??
- ?????????????????????????????qr.setResultlist(products);??
- ?????????????????????????????qr.setTotalrecord(hits.length());??
- ?????????????????????????????hits.close();??
- ???????????????????}? catch ?(CompassException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????????tx.rollback();??
- ???????????????????} finally {??
- ???????????????????????????? if (session!= null ?&&?!session.isClosed())?session.close();??
- ???????????????????}??
- ??????????????????? return ?qr;??
- ?????????}??
- }??
???????? //compass支持增量索引,社會上很多公司,他們的產品都沒有實現增量索引,1>lucene版本比較低,不支持增量索引,2>要增量索引,技術要求稍微有點高
???????? //(晚上 2-3,定時器,把索引文件刪除,重新生成索引)實時性不強,在索引文件更新的時候,用戶是訪問不了的
以上基本都為講解,下面是具體的開發步驟:
步驟一:
導jar:compass的兩個文件,疑問logging文件一般我們已經存在了,lucene的六個文件
步驟二:
配置映射元數據:
設計實體,我們實體已經存在了,所以不用設計了,直接加注解
我們映射產品:
首先我們要加上搜索id
然后我們要分析一下那些是需要搜索的,哪些是不需要搜索的,但是需要顯示在搜索結果中的。如果不需要顯示也不需要索引就不管他
???????? 第三步:
???????? 我們對索引進行填、刪、查
???????? 我們對產品進行保存的時候,我們就應該把索引也保持進去。
???????? 方式一:我們可以重寫我們servicebean的保持方法。添加一個保存到索引里面去的方法。這樣我們就存在一個問題,兩個保存,有一個保存失敗了,另一個保存就無法執行。就導致了數據不同,無法保證兩種保存在同一個事物中
???????? 方式二:把compass集成到spring中,讓他使用spring的事物管理功能。
在我們的spring中添加代碼如下:
- <bean?id= "compass" ? class = "org.compass.spring.LocalCompassBean" >??
- ?????<property?name= "classMappings" >??
- ?????????<list>??
- ????????????<value>cn.itcast.bean.product.ProductInfo</value>??
- ????????????<value>cn.itcast.bean.product.Brand</value>??
- ????????????<value>cn.itcast.bean.product.ProductStyle</value>??
- ????????????<value>cn.itcast.bean.product.ProductType</value>??
- ?????????</list>??
- ?????</property>??
- ?????<property?name= "compassSettings" >??
- ?????????<props>??
- ????????????<prop?key= "compass.engine.analyzer.default.type" >net.paoding.analysis.analyzer.PaodingAnalyzer</prop>??
- ????????????<prop?key= "compass.engine.connection" >file: //d:/index</prop> ??
- ????????????<!--?在內存中建立索引??
- ????????????<prop?key= "compass.engine.connection" >ram: //index</prop> ??
- ????????????-->??
- ????????????<prop?key= "compass.engine.highlighter.default.formatter.simple.pre" ><![CDATA[<font?color= 'red' >]]></prop>??
- ????????????<prop?key= "compass.engine.highlighter.default.formatter.simple.post" ><![CDATA[</font>]]></prop>??
- ????????????<prop?key= "compass.transaction.factory" >org.compass.spring.transaction.SpringSyncTransactionFactory</prop>??
- ?????????</props>??
- ?????</property>??
- ?????<property?name= "transactionManager" ?ref= "transactionManager" ?/>??
- ??</bean>??
?
?
引自:http://osacar.iteye.com/blog/1050977 多謝
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
