首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java Web开发 >

初次使用lucene2.0的心得和疑问解决思路

2012-01-19 
初次使用lucene2.0的心得和疑问这几天一直在看有关lucene的资料,在网上查了下,发现好多文章都是重复的,也

初次使用lucene2.0的心得和疑问
这几天一直在看有关lucene的资料,在网上查了下,发现好多文章都是重复的,也有将的不错的文章,但大多例子都是基于lucene1.4.3的。本人刚接触lucene,在此一点小小的心得和疑问。请看下面:
lucene的基本特性可以参考:
<a   href= "http://www.yyhweb.com/Article.htm?cId=2&fId=3&aId=28 "> 初识lucene </a>
<a   href= "http://www.yyhweb.com/Article.htm?cId=2&fId=3&aId=46 "> Lucene基本使用介绍 </a>
网上大家对中文分词插件IK_CAnalyzer的评价不错,目前IK_CAnalyzer的最新版本是1.4,是在lucene2.0API的基础上开发的。本人下面的例子就是结合lucene2.0和IK_CAnalyzer使用的。

介绍:
例子是对lucene的简单使用,对“文章”的三个基本属性Id,title,content的索引和搜索。
通过ArticleBiz.getForumArt( "10 ");取得一个文章列表。
从此list里取得各文章属性建立索引。

public   class   IndexAndSearch{
      public   static   void   main(String[]   args)   throws   IOException,   ParseException{

    //RAMDirectory   directory   =   new   RAMDirectory();   //   将索引保存到内存中

      String   directory   =   "C:/index ";                           //   将索引保存到硬盘中
      if(!new   File(directory).exists())                          
            new   File(directory).mkdirs();

      //   IK_CAnalyzer的分词器
      MIK_CAnalyzer   mkAnalyzer   =   new   MIK_CAnalyzer();
      try{
                      //   取得文章列表,这部分省略了其与数据库的具体操作。
                      List   alist   =   ArticleBiz.getForumArt( "10 ");

                      //   生成一个IndexWriter,其作用是把每个Document   对象加到索引中来。
                      IndexWriter   writer   =   new   IndexWriter(directory,mkAnalyzer,true);
                      long   s   =   System.currentTimeMillis();//   计算开始时间

                      //   定义Document用来储存索引记录
                        Document   doc   =   null;

                  //   循环从文章列表里对每一篇文章进行索引并将其结果加到以上的writer   里
                      for(int   i=0;i <alist.size();i++){
                        doc   =   new   Document();
                        Article   curArt   =   (Article)   alist.get(i);
                        System.out.println( "index   of   : "+i+ "   the   id   is: "+curArt.getId()+ "   the   title   : "+curArt.getTitle());

                      //   对文章Id,title,content索引,id:存储不分词。title:存储且分词。content:不存储但分词。

                      doc.add(new   Field( "id ",String.valueOf(curArt.getId()),Field.Store.YES,Field.Index.UN_TOKENIZED));


                      doc.add(new   Field( "title ",   curArt.getTitle(),Field.Store.YES,Field.Index.TOKENIZED));
                      doc.add(new   Field( "content ",curArt.getContent(),Field.Store.NO,Field.Index.TOKENIZED));
                      writer.addDocument(doc);             //   加入到writer
                      }
                      writer.optimize();       //   优化,关闭
                        writer.close();
                      System.out.println( "the   process   in: "+(System.currentTimeMillis()-s)+ "   ms ");
            }   catch   (IOException   e)   {
                  System.out.println(e);
            }  

      //查询tilte里含有 "视频 "   或content里含有 "投票 "的文章信息
      Query   query1   =   new   TermQuery(new   Term( "title ",   "视频 "));
      Query   query2   =   new   TermQuery(new   Term( "content ",   "投票 "));
      BooleanQuery   query   =   new   BooleanQuery();
      query.add(query1,null);
      query.add(query2,null);

      //   如果只查询一个字段:不需要BooleanQuery来整合两个Query。
      //   如:只查询tilte里含有 "视频 "
      //   Query   query   =   new   TermQuery(new   Term( "title ",   "视频 "));

      //   生成一个IndexSearcher搜索
      IndexSearcher   indexsearch   =   new   IndexSearcher(directory);

      //   通过indexsearch获得query结果。
      Hits   hits2   =   indexsearch.search(query);
      System.out.println( "begin   search:length: "+hits2.length());
      Document   doc2   =   null;
      int   id   =   0;
      String   title   =   " ";

      //   循环输去搜索结果。
      for(int   i=0;i <hits2.length();i++){
          doc2   =   hits2.doc(i);
          id   =   Integer.valueOf(doc2.get( "id "));
          title   =   doc2.get( "title ");
          System.out.println( "Result   is: "+id+ "   and   the   title   is: "+title);
      }
      System.out.println( "end   search ");
}
}

网上很多例子用的是lucene1.4.3,新版本的lucene在doc.add(new   Field( "content ",curArt.getContent(),Field.Store.NO,Field.Index.TOKENIZED));这些地方与旧版本有很大的区别。
Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要。
Field.Index               Field.Store               说明  


TOKENIZED(分词)       YES                               被分词索引且存储  
TOKENIZED                   NO                                 被分词索引但不存储  
NO                                 YES                               这是不能被搜索的,它只是被搜索内容的附属物。如URL等  
UN_TOKENIZED             YES/NO                       不被分词,它作为一个整体被搜索,搜一部分是搜不出来的  
NO                                   NO                               没有这种用法  

如果要对某Field进行查找,那么一定要把Field.Index设置为TOKENIZED或UN_TOKENIZED。TOKENIZED会对Field的内容进行分词;而UN_TOKENIZED不会,只有全词匹配,该Field才会被选中。
如果Field.Store是No,那么就无法在搜索结果中从索引数据直接提取该域的值,会使null。

以上仅为个人拙见,有谬误的地方,希望大家指正。
同时本人有以下疑问请教,希望得到大家的指点。
1、对于大量数据的来说建立索引的过程肯定是很好费时间的,在论坛搜索中肯定不能够按照上面的例子来做,否则每一个用户搜索都要执行该过程系统就有些吃不消了。
如果将IndexWriter   writer   =   new   IndexWriter(directory,mkAnalyzer,true);第三个参数设为false那么新的文章内容又如何加到原来的索引里呢?
2、索引出来的结果太多的话需要分页,如果一下子全部检索出来的话肯定不科学,但是他又没有类似数据库里的limit限制,如何将大量的查询结果分页呢?
3、删除索引,随着数据的增多,系统索引也增大,在必要的时候可以调用自定义方法删除索引,是否在生成IndexWriter的时候将第三个参数设为false。下次执行的时候就会调用删除索引的方法删除以前的所有索引?

希望高人指点,谢谢!

来源:http://www.yyhweb.com/Article.htm?cId=2&fId=3&aId=50

[解决办法]
2、索引出来的结果太多的话需要分页,如果一下子全部检索出来的话肯定不科学,但是他又没有类似数据库里的limit限制,如何将大量的查询结果分页呢?
--------------------------------
分页在这控制

// 循环输去搜索结果。

for(int i=开始行数;i <结束行数&&i <hits2.length();i++){
doc2 = hits2.doc(i);
id = Integer.valueOf(doc2.get( "id "));
title = doc2.get( "title ");
System.out.println( "Result is: "+id+ " and the title is: "+title);
}

基于lucene的搜索: http://www.ruansou.com/

热点排行