使用Lucene進(jìn)行全文檢索(三)---進(jìn)行搜索

          scud(飛云小俠) http://www.jscud.com 轉(zhuǎn)載請注明來源/作者

          關(guān)鍵字:lucene,html parser,全文檢索,IndexReader,Document,Field,IndexWriter,Term,HTMLPAGE


           無論是建立索引還是分析內(nèi)容,都是為了用戶的搜索服務(wù).
           
           在Lucene中,如果需要使用搜索,需要使用Searcher類,這是一個抽象類,它有2個子類:IndexSearcher和MultiSearcher.
           
           IndexSearcher是對一個索引進(jìn)行搜索,如果你需要對多個索引進(jìn)行搜索,可以使用MultiSearcher.下面的內(nèi)容只介紹了IndexSearcher.
           
           搜索涉及到幾個問題:分頁,組合條件,根據(jù)條件過濾,排序等等.
           
           分頁:分頁在記錄列表的地方都會遇到,這里不在贅述,我也實現(xiàn)過一個保存分頁結(jié)果和顯示結(jié)果的類,用于自己的實際工作,下面也會用到保存分頁結(jié)果的類,代碼如下:

            package com.jscud.support;
            
            
            /**
             * 分頁顯示用的參數(shù).
             *
             * @author scud(飛云小俠) http://www.jscud.com
             * 
             */
            
            public class DivPageInfo
            {
            
                //開始記錄數(shù)
                private int recStart;
            
                //結(jié)束記錄數(shù)
                private int recEnd;
            
                //總頁數(shù)
                private int pageCount;
            
                //當(dāng)前頁
                private int page;
            
                //記錄總數(shù)
                private int recCount;
               
                //每頁記錄數(shù)
                private int perPageRows;
            
                public int getNicePageCount()
                {
                    return getNicePageNum(pageCount);
                }
               
                //get,set等,不在列出
                //......
            
               
                /**
                 * 得到友好的頁數(shù)數(shù)字,頁數(shù)為0時,返回1.
                 *
                 * @return 得到友好的頁數(shù)
                 */
                public static int getNicePageNum(int nPage)
                {
                        if (nPage == 0)
                        {
                                return 1;
                        }
                        else
                        {
                                return nPage;
                        }
                }   
            } 

           顯示分頁結(jié)果的類就需要大家根據(jù)自己使用的框架來具體實現(xiàn)了.我使用的是WebWork.
           
           組合條件:在Lucene中,搜索的條件可以組合的很復(fù)雜,相關(guān)的類有BooleanQuery, FilteredQuery, MultiTermQuery, PhrasePrefixQuery, PhraseQuery, PrefixQuery, RangeQuery, SpanQuery, TermQuery 等等,從而可以組合出很復(fù)雜的條件用于查詢.
           另外QueryParser可以根據(jù)用戶輸入的字符串和設(shè)定的解析器和字段設(shè)置等,可以自動產(chǎn)生新的組合條件用于查詢,例如用戶輸入"john AND black",QueryParser可以自己分析出用戶是需要查詢字段中同時包含"john"和"black"的結(jié)果.
           
           過濾條件:有時候根據(jù)具體的用戶需求,有些記錄對于一些用戶是不可見的,此時就要使用過濾器來防止不合法的用戶看到不應(yīng)該看到的記錄.過濾器同時也可以根據(jù)一些具體的條件來過濾掉一些用戶不想看到的記錄.如果需要實現(xiàn)自己的filter,只要參考QueryFilter,DateFilter實現(xiàn)Filter即可.
           
           排序:有時候,可能需要根據(jù)某個字段進(jìn)行排序,例如按照時間排序.當(dāng)然更多的時候是按照搜索結(jié)果的符合度進(jìn)行排序,lucene默認(rèn)的排序就是按照符合度來進(jìn)行排序的.
           
           進(jìn)行搜索的代碼如下,根據(jù)自己的需要進(jìn)行代碼的修改:
           

           /**
           * 進(jìn)行搜索.
           *
           * 參數(shù)依次為:搜索內(nèi)容(支持lucene語法),當(dāng)前頁,每頁記錄數(shù),分頁信息對象
           *
           */
              public static List search(String searchText, int page, int perpage, final DivPageInfo pageinfo)
              {
                  List docs = new ArrayList();
                 
                  if(!LuceneSearch.indexExist(indexDir)) { return docs; }

                  Searcher searcher = null;
                  try
                  {
                      StandardAnalyzer analyzer = new StandardAnalyzer();

                      //處理檢索條件
                      Query titleQuery = QueryParser.parse(searchText, "title", analyzer);
                      Query contextQuery = QueryParser.parse(searchText, "content", analyzer);
                      Query otherQuery = QueryParser.parse(searchText, "other", analyzer);

                      BooleanQuery query = new BooleanQuery();
                      query.add(titleQuery, false, false);
                      query.add(contextQuery, false, false);
                      query.add(otherQuery, false, false);

                      //分頁檢索
                      searcher = new IndexSearcher(indexDir);
                      Hits hits = searcher.search(query);

                      DivPageInfo.divPage(hits.length(), perpage, page, pageinfo);

                      //取出當(dāng)前頁的記錄
                      for (int i = pageinfo.getRecStart(); i <= pageinfo.getRecEnd(); i++)
                      {
                          docs.add(LuceneDocument.getDocument(hits.doc(i - 1)));
                      }
                  }
                  catch (IOException e)
                  {
                      LogMan.error("Error occur When Search Lucene", e);
                  }
                  catch (ParseException e)
                  {
                      LogMan.error("Error occur When Search Lucene", e);
                  }
                  finally
                  {
                      try
                      {
                          if (null != searcher)
                          {
                              searcher.close();
                          }
                      }
                      catch (IOException e)
                      {
                          LogMan.warn("Close searcher Error");
                      }
                  }

                  return docs;
              }



           
           代碼中出現(xiàn)了一個新的類Hits,Hits是lucene的搜索結(jié)果集,是lazy load的結(jié)果集,只有你真正訪問它,它才去裝載真正的數(shù)據(jù).
           
           代碼中還出現(xiàn)了一個LuceneDocument,這是為了在頁面中顯示而寫的一個輔助類,因為lucene的Document是final的,無法進(jìn)行擴(kuò)展,而要顯示時間字段必須要調(diào)用DateField中的函數(shù),這樣在頁面中顯示就不太直觀了,所以寫了這個輔助類,代碼如下:
           

            package com.jscud.www.support.search;
            
            import java.sql.Timestamp;
            import java.util.Date;
            
            import org.apache.lucene.document.DateField;
            import org.apache.lucene.document.Document;
            import org.apache.lucene.document.Field;
            
            /**
             * 對Lucene的Document的封裝,用于顯示目的.
             *
             * @author scud(飛云小俠) http://www.jscud.com
             *
             */
            public class LuceneDocument
            {
                private Document doc;
               
                public LuceneDocument(Document doc)
                {
                    this.doc = doc;
                }
               
                public static LuceneDocument getDocument(Document doc)
                {
                    return new LuceneDocument(doc);
                }
               
                public String getValue(String name)
                {
                    return doc.get(name);
                }
               
                public Field getField(String name)
                {
                    return doc.getField(name);
                }
               
                public Timestamp getDateTime(String name)
                {
                    String value = doc.get(name);
                    return new Timestamp( DateField.stringToTime(value));
                }
               
                public Date getDate(String name)
                {
                    String value = doc.get(name);
                    return  DateField.stringToDate(value);       
                }    
            }


           
           使用WebWork對結(jié)果集進(jìn)行了顯示,代碼如下:

                    <ww:iterator value="docs">
                    <tr >         
                    <td>
                    <a href="<jscud:contextpath /><ww:property  value="getValue('visiturl')" />"  target="_blank" >
                    <ww:property value="getValue('title')" escape="true" />
                    </a> &nbsp; (<jscud:datetime value="getDateTime('addtime')" />)
                    </td>
                    </tr>
                    </ww:iterator> 
            



           然后調(diào)用分頁信息顯示tag即可.
           
           
           通過以上的應(yīng)用,可以看到,其實使用lucene很簡單,以前總覺得很神秘,所以一直沒有使用過,用過之后才覺得如此簡單.
           
           
           當(dāng)然,對于大容量數(shù)據(jù)下,群集情況下,在網(wǎng)上都有很多解決方案,在此不一一提出,感興趣的讀者可以自己去搜索. :)
           

          posted on 2005-08-12 17:34 Scud(飛云小俠) 閱讀(740) 評論(0)  編輯  收藏 所屬分類: Java

          <2005年8月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導(dǎo)航

          統(tǒng)計

          公告

          文章發(fā)布許可
          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致

          我的郵件
          cnscud # gmail


          常用鏈接

          留言簿(15)

          隨筆分類(113)

          隨筆檔案(103)

          相冊

          友情鏈接

          技術(shù)網(wǎng)站

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 台北县| 吴堡县| 南涧| 共和县| 宜良县| 逊克县| 明水县| 淄博市| 宜春市| 合山市| 岳池县| 缙云县| 大埔区| 威远县| 张家港市| 宁蒗| 桂阳县| 镇沅| 西华县| 南郑县| 阿拉善盟| 六盘水市| 德令哈市| 彭山县| 砚山县| 巢湖市| 百色市| 板桥市| 凤山市| 抚宁县| 汝阳县| 山东省| 武汉市| 方城县| 彭泽县| 二连浩特市| 登封市| 博客| 天柱县| 鱼台县| 闵行区|