龙v战

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Lucene 其实很简单的,它最主要就是做两件事:建立索引和进行搜索
来看一些在lucene中使用的术语,这里并不打算作详细的介绍,只是点一下而已----因为这一个世界有一种好东西,叫搜索。

IndexWriter:lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。

Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

Directory:索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。

Document:文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。

Field:字段。

IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具;

Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。

QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。

Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。

上面作了一大堆名词解释,下面就看几个简单的实例吧:
1、简单的的StandardAnalyzer测试例子

Java代码
  1. package lighter.javaeye.com;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.StringReader;   
  5.   
  6. import org.apache.lucene.analysis.Analyzer;   
  7. import org.apache.lucene.analysis.Token;   
  8. import org.apache.lucene.analysis.TokenStream;   
  9. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  10.   
  11. public class StandardAnalyzerTest    
  12. {   
  13.     //构造函数,   
  14.     public StandardAnalyzerTest()   
  15.     {   
  16.     }   
  17.     public static void main(String[] args)    
  18.     {   
  19.         //生成一个StandardAnalyzer对象   
  20.         Analyzer aAnalyzer = new StandardAnalyzer();   
  21.         //测试字符串   
  22.         StringReader sr = new StringReader("lighter javaeye com is the are on");   
  23.         //生成TokenStream对象   
  24.         TokenStream ts = aAnalyzer.tokenStream("name", sr);    
  25.         try {   
  26.             int i=0;   
  27.             Token t = ts.next();   
  28.             while(t!=null)   
  29.             {   
  30.                 //辅助输出时显示行号   
  31.                 i++;   
  32.                 //输出处理后的字符   
  33.                 System.out.println("第"+i+"行:"+t.termText());   
  34.                 //取得下一个字符   
  35.                 t=ts.next();   
  36.             }   
  37.         } catch (IOException e) {   
  38.             e.printStackTrace();   
  39.         }   
  40.     }   
  41. }  

 


显示结果:

引用
第1行:lighter
第2行:javaeye
第3行:com


提示一下:
StandardAnalyzer是lucene中内置的"标准分析器",可以做如下功能:
1、对原有句子按照空格进行了分词
2、所有的大写字母都可以能转换为小写的字母
3、可以去掉一些没有用处的单词,例如"is","the","are"等单词,也删除了所有的标点
查看一下结果与"new StringReader("lighter javaeye com is the are on")"作一个比较就清楚明了。
这里不对其API进行解释了,具体见lucene的官方文档。需要注意一点,这里的代码使用的是lucene2的API,与1.43版有一些明显的差别。

2、看另一个实例,简单地建立索引,进行搜索

Java代码
  1. package lighter.javaeye.com;   
  2. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  3. import org.apache.lucene.document.Document;   
  4. import org.apache.lucene.document.Field;   
  5. import org.apache.lucene.index.IndexWriter;   
  6. import org.apache.lucene.queryParser.QueryParser;   
  7. import org.apache.lucene.search.Hits;   
  8. import org.apache.lucene.search.IndexSearcher;   
  9. import org.apache.lucene.search.Query;   
  10. import org.apache.lucene.store.FSDirectory;   
  11.   
  12. public class FSDirectoryTest {   
  13.   
  14.     //建立索引的路径   
  15.     public static final String path = "c:\\index2";   
  16.   
  17.     public static void main(String[] args) throws Exception {   
  18.         Document doc1 = new Document();   
  19.         doc1.add( new Field("name""lighter javaeye com",Field.Store.YES,Field.Index.TOKENIZED));   
  20.   
  21.         Document doc2 = new Document();   
  22.         doc2.add(new Field("name""lighter blog",Field.Store.YES,Field.Index.TOKENIZED));   
  23.   
  24.         IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true), new StandardAnalyzer(), true);   
  25.         writer.setMaxFieldLength(3);   
  26.         writer.addDocument(doc1);   
  27.         writer.setMaxFieldLength(3);   
  28.         writer.addDocument(doc2);   
  29.         writer.close();   
  30.   
  31.         IndexSearcher searcher = new IndexSearcher(path);   
  32.         Hits hits = null;   
  33.         Query query = null;   
  34.         QueryParser qp = new QueryParser("name",new StandardAnalyzer());   
  35.            
  36.         query = qp.parse("lighter");   
  37.         hits = searcher.search(query);   
  38.         System.out.println("查找\"lighter\" 共" + hits.length() + "个结果");   
  39.   
  40.         query = qp.parse("javaeye");   
  41.         hits = searcher.search(query);   
  42.         System.out.println("查找\"javaeye\" 共" + hits.length() + "个结果");   
  43.   
  44.     }   
  45.   
  46. }  

 


运行结果:

Java代码
  1. 查找"lighter" 共2个结果   
  2. 查找"javaeye" 共1个结果  

 

 

 

 

实例二:

说明一下,这一篇文章的用到的lucene,是用2.0版本的,主要在查询的时候2.0版本的lucene与以前的版本有了一些区别.
1、在windows系统下的的C盘,建一个名叫s的文件夹,在该文件夹里面随便建三个txt文件,随便起名啦,就叫"1.txt","2.txt"和"3.txt"啦
其中1.txt的内容如下:

Java代码
  1. 中华人民共和国   
  2. 全国人民   
  3. 2006年  

而"2.txt"和"3.txt"的内容也可以随便写几写,这里懒写,就复制一个和1.txt文件的内容一样吧

2、下载lucene包,放在classpath路径中
建立索引:
Java代码
  1. package lighter.javaeye.com;   
  2.   
  3. import java.io.BufferedReader;   
  4. import java.io.File;   
  5. import java.io.FileInputStream;   
  6. import java.io.IOException;   
  7. import java.io.InputStreamReader;   
  8. import java.util.Date;   
  9.   
  10. import org.apache.lucene.analysis.Analyzer;   
  11. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  12. import org.apache.lucene.document.Document;   
  13. import org.apache.lucene.document.Field;   
  14. import org.apache.lucene.index.IndexWriter;   
  15.   
  16. /**  
  17.  * author lighter date 2006-8-7  
  18.  */  
  19. public class TextFileIndexer {   
  20.     public static void main(String[] args) throws Exception {   
  21.         /* 指明要索引文件夹的位置,这里是C盘的S文件夹下 */  
  22.         File fileDir = new File("c:\\s");   
  23.   
  24.         /* 这里放索引文件的位置 */  
  25.         File indexDir = new File("c:\\index");   
  26.         Analyzer luceneAnalyzer = new StandardAnalyzer();   
  27.         IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer,   
  28.                 true);   
  29.         File[] textFiles = fileDir.listFiles();   
  30.         long startTime = new Date().getTime();   
  31.            
  32.         //增加document到索引去   
  33.         for (int i = 0; i < textFiles.length; i++) {   
  34.             if (textFiles[i].isFile()   
  35.                     && textFiles[i].getName().endsWith(".txt")) {   
  36.                 System.out.println("File " + textFiles[i].getCanonicalPath()   
  37.                         + "正在被索引....");   
  38.                 String temp = FileReaderAll(textFiles[i].getCanonicalPath(),   
  39.                         "GBK");   
  40.                 System.out.println(temp);   
  41.                 Document document = new Document();   
  42.                 Field FieldPath = new Field("path", textFiles[i].getPath(),   
  43.                         Field.Store.YES, Field.Index.NO);   
  44.                 Field FieldBody = new Field("body", temp, Field.Store.YES,   
  45.                         Field.Index.TOKENIZED,   
  46.                         Field.TermVector.WITH_POSITIONS_OFFSETS);   
  47.                 document.add(FieldPath);   
  48.                 document.add(FieldBody);   
  49.                 indexWriter.addDocument(document);   
  50.             }   
  51.         }   
  52.         //optimize()方法是对索引进行优化   
  53.         indexWriter.optimize();   
  54.         indexWriter.close();   
  55.            
  56.         //测试一下索引的时间   
  57.         long endTime = new Date().getTime();   
  58.         System.out   
  59.                 .println("这花费了"  
  60.                         + (endTime - startTime)   
  61.                         + " 毫秒来把文档增加到索引里面去!"  
  62.                         + fileDir.getPath());   
  63.     }   
  64.   
  65.     public static String FileReaderAll(String FileName, String charset)   
  66.             throws IOException {   
  67.         BufferedReader reader = new BufferedReader(new InputStreamReader(   
  68.                 new FileInputStream(FileName), charset));   
  69.         String line = new String();   
  70.         String temp = new String();   
  71.            
  72.         while ((line = reader.readLine()) != null) {   
  73.             temp += line;   
  74.         }   
  75.         reader.close();   
  76.         return temp;   
  77.     }   
  78. }  


索引的结果:
Java代码
  1. File C:\s\1.txt正在被索引....   
  2. 中华人民共和国全国人民2006年   
  3. File C:\s\2.txt正在被索引....   
  4. 中华人民共和国全国人民2006年   
  5. File C:\s\3.txt正在被索引....   
  6. 中华人民共和国全国人民2006年   
  7. 这花费了297 毫秒来把文档增加到索引里面去!c:\s  


3、建立了索引之后,查询啦....
Java代码
  1. package lighter.javaeye.com;   
  2.   
  3. import java.io.IOException;   
  4.   
  5. import org.apache.lucene.analysis.Analyzer;   
  6. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  7. import org.apache.lucene.queryParser.ParseException;   
  8. import org.apache.lucene.queryParser.QueryParser;   
  9. import org.apache.lucene.search.Hits;   
  10. import org.apache.lucene.search.IndexSearcher;   
  11. import org.apache.lucene.search.Query;   
  12.   
  13. public class TestQuery {   
  14.     public static void main(String[] args) throws IOException, ParseException {   
  15.         Hits hits = null;   
  16.         String queryString = "中华";   
  17.         Query query = null;   
  18.         IndexSearcher searcher = new IndexSearcher("c:\\index");   
  19.   
  20.         Analyzer analyzer = new StandardAnalyzer();   
  21.         try {   
  22.             QueryParser qp = new QueryParser("body", analyzer);   
  23.             query = qp.parse(queryString);   
  24.         } catch (ParseException e) {   
  25.         }   
  26.         if (searcher != null) {   
  27.             hits = searcher.search(query);   
  28.             if (hits.length() > 0) {   
  29.                 System.out.println("找到:" + hits.length() + " 个结果!");   
  30.             }   
  31.         }   
  32.     }   
  33.   
  34. }  


其运行结果:
引用
找到:3 个结果!


具体的API的用法,这里就不说了,具体的做法参考lucene的官方文档吧...

 

 

 

实例三:

 Lucene,这是官方称谓,也有许多人叫它Lucence,做搜索和分词用的工具包.也有人说是Java下的搜索引擎框架库,见仁见智的说法罢了.不管叫什么,确实非常有用,比如做全站的搜索,其实它的用处远大于此,但凡涉及到文本搜索的地方就能用到它.我们就以做全站搜索为例,演示一下如何应用Lucene建立索引.

Java代码
  1. public void index(List<IArticle> list)   
  2. {   
  3.   //IArticle接口提供getName(标题)和getContent(内容)   
  4.   //list就是从数据库里查询出来的要建立索引的对象的列表   
  5.   if(list != null && list.size() > 0)   
  6.   {   
  7.     try {   
  8.            //标记是否重新建立索引,true为重新建立索引   
  9.            boolean flag = true;   
  10.            //如果已存在索引,则追加索引   
  11.            if(IndexReader.indexExists(path))   
  12.       {   
  13.          flag = false;   
  14.            }   
  15.       ChineseAnalyzer ca = new ChineseAnalyzer();   
  16.       IndexWriter indexWriter = new IndexWriter("c:/lucene/index",ca,flag);            
  17.       Document doc = null;   
  18.       for(int i=0;i<list.size();i++)   
  19.           {   
  20.         doc = new Document();   
  21.         doc.add(new Field("title",article.getName(),Field.Store.YES,Field.Index.TOKENIZED));   
  22.        //添加内容属性,内容只索引,不存储   
  23.        doc.add(new Field("content",new StringReader(list.get(i).getContent())));   
  24.        indexWriter.addDocument(doc);   
  25.       }   
  26.            //优化并关闭   
  27.       indexWriter.optimize();   
  28.       indexWriter.close();   
  29.        } catch (Exception e)    
  30.        {   
  31.       // TODO 自动生成 catch 块   
  32.       //e.printStackTrace();   
  33.        }   
  34.   }   
  35. }  

 


简单说下需要注意的地方:
1.ChineseAnalyzer ca = new ChineseAnalyzer();这个是分析器,Lucene内置多个,处理中文搜索我会用ChineseAnalyzer.
2.IndexWriter indexWriter = new IndexWriter(c:/lucene/index,ca,true);处理索引的类,注意其构造方法里的最后一个参数,如果为true则表示,下次建立索引时会清除这次建立的索引重新建立索引,如果为false则表示追加索引,在原来索引的基础上追加.看实际情况定true或false.
3.doc.add(new Field("title",article.getName(),Field.Store.YES,Field.Index.TOKENIZED));这一句表示为文章标题建立索引并存储.
4.doc.add(new Field("content",new StringReader(list.get(i).getContent())));这句是为内容建立索引但不存储
   这样我们就为文章对象建立好索引了,然后就可以利用Lucene的其他类对这个索引目录进行搜索了,关于搜索部分我们稍后再补充上.
   下面是搜索部分的代码,写的简陋了点,比较简单,不再多说,请参看注释:

Java代码
  1. public class Search   
  2. {   
  3.   //定义一个索引搜索类对象   
  4.   private IndexSearcher searcher = null;   
  5.   //定义一个Query对象   
  6.   private Query query = null;   
  7.   //定义中文分析器   
  8.   ChineseAnalyzer analyzer = new ChineseAnalyzer();   
  9.   //构造方法里完成searcher的实例化   
  10.   public Search()   
  11.   {   
  12.     try  
  13.     {   
  14.      //这里的参数就是上面我们生成索引的目录   
  15.      searcher = new IndexSearcher(IndexReader.open("c:/lucene/index"));   
  16.     }catch(Exception e)   
  17.     {   
  18.       e.printStackTrace();   
  19.     }   
  20.   }   
  21.   public Hits search(String keyword) throws Exception   
  22.   {   
  23.     //开始搜索的时间   
  24.     Date start = new Date();   
  25.     //对我们索引的content字段进行搜索   
  26.     QueryParser qp = new QueryParser("content",analyzer);   
  27.     this.query = qp.parse(keyword);   
  28.     Hits hits = this.searcher.search(query);   
  29.     Date end = new Date();   
  30.     System.out.println("检索完成,用时"+(end.getTime()-start.getTime())+"毫秒");   
  31.     //////////打印测试////////   
  32.     if(hits != null && hits.length() > 0)   
  33.     {   
  34.       for(int i = 0; i < hits.length(); i++)   
  35.       {   
  36.         try  
  37.         {   
  38.           Document doc = hits.doc(i);   
  39.           System.out.println("结果"+(i+1)+":"+doc.get("title")+" createTime:"+doc.get("content"));    
  40.           //System.out.println(doc.get("path"));   
  41.         }catch(Exception e)   
  42.         {   
  43.           e.printStackTrace();   
  44.         }   
  45.       }   
  46.     }   
  47.     return hits;   
  48.   }   
  49.   ///调用,主方法   
  50.   public static void main(String[] args)   
  51.   {   
  52.     try    
  53.     {   
  54.       Search test = new Search();   
  55.       Hits h = test.search("你好");   
  56.     } catch (Exception e)    
  57.     {   
  58.       // TODO 自动生成 catch 块   
  59.        e.printStackTrace();   
  60.     }   
  61.   }   
  62. }  

 

 

 

 

实例四(Lucene索引SQL2000(完整篇))

原文: http://www.wujianrong.com/archives/2007/03/lucene_7.html

1.写一段传统的JDBC程序,讲每条的用户信息从数据库读取出来
2.针对每条用户记录,建立一个lucene document
Document doc = new Document();
并根据你的需要,将用户信息的各个字段对应luncene document中的field 进行添加,如:
doc.add(new Field("NAME","USERNAME",Field.Store.YES,Field.Index.UN_TOKENIZED));
然后将该条doc加入到索引中, 如: luceneWriter.addDocument(doc);
这样就建立了lucene的索引库
3.编写对索引库的搜索程序(看lucene文档),通过对lucene的索引库的查找,你可以快速找到对应记录的ID
4.通过ID到数据库中查找相关记录

用Lucene索引数据库

  Lucene,作为一种全文搜索的辅助工具,为我们进行条件搜索,无论是像Google,Baidu之类的搜索引 擎,还是论坛中的搜索功能,还是其它C/S架构的搜索,都带来了极大的便利和比较高的效率。本文主要是利用Lucene对MS Sql Server 2000进行建立索引,然后进行全文索引。至于数据库的内容,可以是网页的内容,还是其它的。本文中数据库的内容是图书馆管理系统中的某个作者表- Authors表。
  因为考虑到篇幅的问题,所以该文不会讲的很详细,也不可能讲的很深。

  本文以这样的结构进行:

  1.介绍数据库中Authors表的结构

  2.为数据库建立索引

  3.为数据库建立查询功能

  4.在web界面下进行查询并显示结果

  1.介绍数据库中Authors表的结构

字段名称         字段类型         字段含义

Au_id                Varchar(11)    作者号
Au_name        Varchar(60)     作者名
Phone             Char(12)           电话号码
Address          Varchar(40)      地址
City                   Varchar(20)     城市
State                Char(2)             省份
Zip                    Char(5)             邮编
contract            Bit(1)                外键(关系不大)

表中的部分内容:

  2.为数据库建立索引

  首先建立一个类TestLucene.java。这个类就是对数据库进行建立索引,编写查询条件等。

  当然,最开始就是建立数据库连接。连接代码这里就省略了。^_^

  接着,新建一个方法getResutl(String),它返回的是数据库表Authors的内容。具体代码如下:

    public ResultSet getResult(String sql){
      try{
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        return rs;
      }
      catch(SQLException e){
        System.out.println(e);
      }
      return null;
    }

  然后,为数据库建立索引。

   首先要定义一个IndexWriter(),它是将索引写进Lucene自己的数据库中,它存放的位置是有你自己定义的。在定义IndexWriter 是需要指定它的分析器。Lucene自己自带有几个分析器,例如:StandarAnalyzer(),SimpleAnalyzer(), StopAnalyzer()等。它作用是对文本进行分析,判断如何进行切词。
接着,要定义一个Document。Document相当于二维表中一行数据一样。Document里包含的是Field字段,Field相当于数据库中一列,也就是一个属性,一个字段。
最后应该对IndexWriter进行优化,方法很简单,就是writer.optimize().
具体代码如下:

  public void Index(ResultSet rs){
      try{
        IndexWriter writer = new IndexWriter("d:/index/", getAnalyzer(), true);
        while(rs.next()){
            Document doc=new Document();
            doc.add(Field.Keyword("id",rs.getString("au_id")));
            doc.add(Field.Text("name",rs.getString("au_name")));
            doc.add(Field.UnIndexed("address",rs.getString("address")));
            doc.add(Field.UnIndexed("phone",rs.getString("phone")));
            doc.add(Field.Text("City",rs.getString("city")));
            writer.addDocument(doc);
          }
        writer.optimize();
        writer.close();
      }
      catch(IOException e){
        System.out.println(e);
      }
      catch(SQLException e){
        System.out.println(e);
      }
    }

    public Analyzer getAnalyzer(){
      return new StandardAnalyzer();
    }

  3.为数据库建立查询功能

  在类TestLucene中建立一个新的方法searcher(String),它返回的是一个搜索的结构集,相当于数据库中的ResultSet一样。它代的参数是你要查询的内容。这里,我把要查询的字段写死了。你可以在添加一个参数表示要查询的字段。
这里主要有两个对象IndexSearcher和Query。IndexSearcher是找到索引数据库,Query是处理搜索,它包含了三个参数:查询内容,查询字段,分析器。
具体代码如下:

  public Hits seacher(String queryString){
      Hits hits=null;;
      try{
        IndexSearcher is = new IndexSearcher("D:/index/");
        Query query=QueryParser.parse(queryString,"City",getAnalyzer());
        hits=is.search(query);
      }catch(Exception e){
        System.out.print(e);
      }
      return hits;
    }

  4.在web界面下进行查询并显示结果

  这里建立一个Jsp页面TestLucene.jsp进行搜索。

  在TestLucene.jsp页面中首先引入类


<%@ page import="lucenetest.LucentTest"%>
<%@ page import="org.apache.lucene.search.*,org.apache.lucene.document.*" %>


  然后定义一个LuceneTest对象,获取查询结果集:

  LucentTest lucent=new LucentTest();
  Hits hits=lucent.seacher(request.getParameter("queryString"));

  定义一个Form,建立一个查询环境:

<form action="TestLucene.jsp">
  <input  type="text" name="queryString"/>
  <input type="submit" value="搜索"/>
</form>

  显示查询结果:

<table>
  <%if(hits!=null){%>
  <tr>
    <td>作者号</td>
    <td>作者名</td>
    <td>地址</td>
    <td>电话号码</td>
  </tr>

 <% for(int i=0;i<hits.length();i++){
    Document doc=hits.doc(i);
   %>
    <tr>
    <td><%=doc.get("id") %></td>
    <td><%=doc.get("name") %></td>
    <td><%=doc.get("address") %></td>
    <td><%=doc.get("phone") %></td>
  </tr>
 <% }}%>
</table>


用Lucene-1.3-final为网站数据库建立索引

下是看了lnboy写的《用lucene建立大富翁论坛的全文检索》后写的测试代码。
 
为数据库cwb.mdb建立全文索引的indexdb.jsp

<%@ page import ="org.apache.lucene.analysis.standard.*" %>  
<%@ page import="org.apache.lucene.index.*" %> 
<%@ page import="org.apache.lucene.document.*" %> 
<%@ page import="lucene.*" %> 
<%@ page contentType="text/html; charset=GBK" %> 
<% 
      long start = System.currentTimeMillis(); 
      String aa=getServletContext().getRealPath("/")+"index";    
      IndexWriter writer = new IndexWriter(aa, new StandardAnalyzer(), true); 
    try { 
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();

 String url = "jdbc:odbc:driver={Microsoft Access Driver (*.mdb)}
       ;DBQ=d:\\Tomcat 5.0\\webapps\\zz3zcwbwebhome\\WEB-INF\\cwb.mdb"; 
      Connection conn = DriverManager.getConnection(url); 
      Statement stmt = conn.createStatement(); 
      ResultSet rs = stmt.executeQuery( 
          "select Article_id,Article_name,Article_intro from Article"); 
      while (rs.next()) { 
             writer.addDocument(mydocument.Document(rs.getString("Article_id"),
                rs.getString("Article_name"),rs.getString("Article_intro"))); 
      } 
      rs.close(); 
      stmt.close(); 
      conn.close(); 
  
      out.println("索引创建完毕");    
      writer.optimize(); 
      writer.close(); 
      out.print(System.currentTimeMillis() - start); 
      out.println(" total milliseconds"); 

    } 
    catch (Exception e) { 
      out.println(" 出错了 " + e.getClass() + 
                         "\n 错误信息为: " + e.getMessage()); 
    } 
 %> 

用于显示查询结果的aftsearch.jsp 
<%@ page import="org.apache.lucene.search.*" %> 
<%@ page import="org.apache.lucene.document.*" %> 
<%@ page import="lucene.*" %> 
<%@ page import = "org.apache.lucene.analysis.standard.*" %>  
<%@ page import="org.apache.lucene.queryParser.QueryParser" %> 
<%@ page contentType="text/html; charset=GBK" %> 
<% 
    String keyword=request.getParameter("keyword"); 
     keyword=new String(keyword.getBytes("ISO8859_1"));  
      out.println(keyword); 
   try { 
       String aa=getServletContext().getRealPath("/")+"index";    
      Searcher searcher = new IndexSearcher(aa); 
      Query query = QueryParser.parse(keyword, "Article_name", new StandardAnalyzer()); 
     
      out.println("正在查找: " + query.toString("Article_name")+"<br>"); 
      Hits hits = searcher.search(query); 
      System.out.println(hits.length() + " total matching documents"); 
      java.text.NumberFormat format = java.text.NumberFormat.getNumberInstance(); 
      for (int i = 0; i < hits.length(); i++) { 
        //开始输出查询结果 
        Document doc = hits.doc(i); 
        out.println(doc.get("Article_id")); 
        out.println("准确度为:" + format.format(hits.score(i) * 100.0) + "%"); 
        out.println(doc.get("Article_name")+"<br>"); 
       // out.println(doc.get("Article_intro")); 
      } 
    }catch (Exception e) { 
      out.println(" 出错了 " + e.getClass() +"\n 错误信息为: " + e.getMessage()); 
    } 
%> 

辅助类: 
package lucene; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.document.DateField; 

public class mydocument { 
public static Document Document(String Article_id,String Article_name,String Article_intro){ 
     Document doc = new Document(); 
      doc.add(Field.Keyword("Article_id", Article_id)); 
      doc.add(Field.Text("Article_name", Article_name)); 
      doc.add(Field.Text("Article_intro", Article_intro)); 
      return doc; 
  } 
  public mydocument() { 
  } 
}

用lucene为数据库搜索建立增量索引

用 lucene 建立索引不可能每次都重新开始建立,而是按照新增加的记录,一次次的递增
建立索引的IndexWriter类,有三个参数


IndexWriter writer = new IndexWriter(path, new StandardAnalyzer(),isEmpty);

其中第三个参数是bool型的,指定它可以确定是增量索引,还是重建索引.
对于从数据库中读取的记录,譬如要为文章建立索引,我们可以记录文章的id号,然后下次再次建立索引的时候读取存下的id号,从此id后往下继续增加索引,逻辑如下.

建立增量索引,主要代码如下

public void createIndex(String path)
{
     Statement myStatement = null;
     String articleId="0";
     //读取文件,获得文章id号码,这里只存最后一篇索引的文章id
    try {
        FileReader fr = new FileReader("**.txt");
        BufferedReader br = new BufferedReader(fr);                
        articleId=br.readLine();
        if(articleId==null||articleId=="")
        articleId="0";
        br.close();
        fr.close();
      } catch (IOException e) {
        System.out.println("error343!");
        e.printStackTrace();
      }
    try {
        //sql语句,根据id读取下面的内容
        String sqlText = "*****"+articleId;
        myStatement = conn.createStatement();
        ResultSet rs = myStatement.executeQuery(sqlText);
       //写索引
        while (rs.next()) {
         Document doc = new Document();
         doc.add(Field.Keyword("**", DateAdded));
         doc.add(Field.Keyword("**", articleid));
         doc.add(Field.Text("**", URL));   
         doc.add(Field.Text("**", Content));
         doc.add(Field.Text("**", Title));   
         try{
            writer.addDocument(doc);
          }
          catch(IOException e){
            e.printStackTrace();
         }
           //将我索引的最后一篇文章的id写入文件
          try {
           FileWriter fw = new FileWriter("**.txt");
           PrintWriter out = new PrintWriter(fw);   
           out.close();
           fw.close();
           } catch (IOException e) {
             e.printStackTrace();
           }
         }
            ind.Close();
            System.out.println("ok.end");
         }
         catch (SQLException e){
            e.printStackTrace();
        }
        finally {
            //数据库关闭操作
        }       
    }

然后控制是都建立增量索引的时候根据能否都到id值来设置IndexWriter的第三个参数为true 或者是false


 boolean isEmpty = true;
 try {
    FileReader fr = new FileReader("**.txt");
    BufferedReader br = new BufferedReader(fr);                
    if(br.readLine()!= null) {
        isEmpty = false;
     }
     br.close();
     fr.close();
    } catch (IOException e) {
       e.printStackTrace();
  }
           
  writer = new IndexWriter(Directory, new StandardAnalyzer(),isEmpty);

 

 

 

Lucene进阶:and 和or的条件查询

文章分类:Java编程

原创作者: DavyLee   阅读:957次   评论:0条   更新时间:2007-09-24     收藏
     在用Lucene实现全站搜索的过程中,很可能会遇到这样的问题,只所有某种特定的信息资源,而不是全部.如:某综合性站点,有新闻,产品,论坛,Blog,视频等资源,而搜索的时候先选一个类型(下拉列表),再输入关键字进行搜索(当然,这种情况可以直接用sql来实现,我们这里是基于lucene的实现考虑).这种情况下,就要用到and和or的查询了.这里假设索引已经建立好了(如何建立索引请参考:http://www.javaeye.com/topic/125599),索引字段为title(标题), type(资源类型,表示新闻还是产品,product为产品,news表新闻),则实现方法如下:
Java代码
  1. /**    
  2. * 根据信息分类和关键词进行查询    
  3. * @param type,资源的类型,其值为news或product    
  4. * @param searchKey,搜索的关键字    
  5. * @return Hits    
  6. */     
  7. public Hits executeSearch(String type,String keyword)      
  8. {      
  9.   Hits result = null;      
  10.   if(type != null && !type.equals("") && keyword != null && !keyword.equals(""))      
  11.   {      
  12.     try       
  13.     {      
  14.       //根据关键字构造一个数组      
  15.       String[] key = new String[]{keyword,type};      
  16.       //同时声明一个与之对应的字段数组      
  17.       String[] fields = {"title","type"};      
  18.       //声明BooleanClause.Occur[]数组,它表示多个条件之间的关系      
  19.       BooleanClause.Occur[] flags=new BooleanClause.Occur[]{BooleanClause.Occur.MUST,BooleanClause.Occur.MUST};      
  20.       ChineseAnalyzer analyzer = new ChineseAnalyzer();      
  21.       //用MultiFieldQueryParser得到query对象      
  22.       Query query = MultiFieldQueryParser.parse(key, fields, flags, analyzer);      
  23.       //c:/index表示我们的索引文件所在的目录      
  24.       IndexSearcher searcher = new IndexSearcher("c:/index");      
  25.       //查询结果      
  26.       result = searcher.search(query);      
  27.     } catch (Exception e)      
  28.     {      
  29.       e.printStackTrace();      
  30.     }      
  31.   }      
  32.   return result;      
  33. }    

 lizi:


LuceneIndexImpl 

posted on 2010-03-22 17:24  龙v战  阅读(566)  评论(0编辑  收藏  举报