【Lucene3.6.2入门系列】第01节_HelloWord

来源:互联网 发布:数控车自动编程软件 编辑:程序博客网 时间:2024/05/21 09:05
[java] view plaincopyprint?
  1. package com.jadyer.lucene;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileReader;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  8. import org.apache.lucene.document.Document;  
  9. import org.apache.lucene.document.Field;  
  10. import org.apache.lucene.index.IndexReader;  
  11. import org.apache.lucene.index.IndexWriter;  
  12. import org.apache.lucene.index.IndexWriterConfig;  
  13. import org.apache.lucene.queryParser.QueryParser;  
  14. import org.apache.lucene.search.IndexSearcher;  
  15. import org.apache.lucene.search.Query;  
  16. import org.apache.lucene.search.ScoreDoc;  
  17. import org.apache.lucene.search.TopDocs;  
  18. import org.apache.lucene.store.Directory;  
  19. import org.apache.lucene.store.FSDirectory;  
  20. import org.apache.lucene.util.Version;  
  21.   
  22. /** 
  23.  * 【Lucene3.6.2入门系列】第01节_HelloWord 
  24.  * @see 这里只需用到一个lucene-core-3.6.2.jar 
  25.  * @see Lucene官网:http://lucene.apache.org 
  26.  * @see Lucene下载:http://archive.apache.org/dist/lucene/java/ 
  27.  * @see Lucene文档:http://wiki.apache.org/lucene-java/ 
  28.  * @see ------------------------------------------------------------------------------------------------------------- 
  29.  * @see 1)对于全文搜索工具,都是由索引、分词、搜索三部分组成 
  30.  * @see 2)被存储和被索引,是两个独立的概念 
  31.  * @see ------------------------------------------------------------------------------------------------------------- 
  32.  * @see 域的存储选项 
  33.  * @see Field.Store.YES--会把该域中的内容存储到文件中,方便进行文本的还原 
  34.  * @see Field.Store.NO---表示该域中的内容不存储到文件中,但允许被索引,且内容无法完全还原(doc.get("##")) 
  35.  * @see ------------------------------------------------------------------------------------------------------------- 
  36.  * @see 域的索引选项 
  37.  * @see Field.Index.ANALYZED----------------进行分词和索引,适用于标题、内容等 
  38.  * @see Field.Index.NOT_ANALYZED------------进行索引但不分词(如身份证号、姓名、ID等),适用于精确搜索 
  39.  * @see Field.Index.ANALYZED_NOT_NORMS------进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息 
  40.  * @see Field.Index.NOT_ANALYZED_NOT_NORMS--即不进行分词也不存储norms信息 
  41.  * @see Field.Index.NO----------------------不进行索引 
  42.  * @see norms:当数据被搜索出来后,便涉及到排序的问题,而排序是有一些评分规则的,于是NORMS中就存储了这些排序的信息 
  43.  * @see -------------------------------------------------------------------------------------------------------------  
  44.  * @see 域选项最佳实践 
  45.  * @see Field.Store   Field.Index              域值 
  46.  * @see       YES     NOT_ANALYZED_NOT_NORMS   标识符(主键、文件名),电话号码,身份证号,姓名,日期 
  47.  * @see       YES     ANALYZED                 文档标题和摘要 
  48.  * @see        NO     ANALYZED                 文档正文 
  49.  * @see        NO     NOT_ANALYZED             隐藏关键字 
  50.  * @see       YES     NO                       文档类型,数据库主键(不进行索引) 
  51.  * @see ------------------------------------------------------------------------------------------------------------- 
  52.  * @create Jun 29, 2012 4:20:19 PM 
  53.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  54.  */  
  55. public class HelloWord {  
  56.     private static final String PATH_OF_FILE = "myExample/01_file/";   //待索引文件的目录  
  57.     private static final String PATH_OF_INDEX = "myExample/01_index/"//存放索引文件的目录  
  58.       
  59.     /** 
  60.      * 创建索引 
  61.      * @see --------------------------------------------------------------------------------------------------------- 
  62.      * @see 1、创建Directory-----------------指定索引被保存的位置 
  63.      * @see 2、创建IndexWriter---------------通过IndexWriter写索引 
  64.      * @see 3、创建Document对象---------------我们索引的有可能是一段文本or数据库中的一张表 
  65.      * @see 4、为Document添加Field------------相当于Document的标题、大小、内容、路径等等,二者类似于数据库表中每条记录和字段的关系 
  66.      * @see 5、通过IndexWriter添加文档到索引中 
  67.      * @see 6、关闭IndexWriter----------------用完IndexWriter之后,必须关闭之 
  68.      * @see --------------------------------------------------------------------------------------------------------- 
  69.      * @see _0.fdt和_0.fdx文件--保存域中所存储的数据(Field.Store.YES条件下的) 
  70.      * @see _0.fnm文件----------保存域选项的数据(即new Field(name, value)中的name) 
  71.      * @see _0.frq文件----------记录相同的文件(或查询的关键字)出现的次数,它是用来做评分和排序的 
  72.      * @see _0.nrm文件----------存储一些评分信息 
  73.      * @see _0.prx文件----------记录偏移量 
  74.      * @see _0.tii和_0.tis文件--存储索引里面的所有内容信息 
  75.      * @see segments_1文件------它是段文件,Lucene首先会到段文件中查找相应的索引信息 
  76.      * @see --------------------------------------------------------------------------------------------------------- 
  77.      */  
  78.     public void createIndex(){  
  79.         Directory directory = null;  
  80.         IndexWriter writer = null;  
  81.         Document doc = null;  
  82.         try{  
  83.             //FSDirectory会根据当前的运行环境打开一个合理的基于File的Directory(若在内存中创建索引则new RAMDirectory())  
  84.             //这里是在硬盘上"D:/OS_Folder/Desktop/luceneDemo/index01/"文件夹中创建索引  
  85.             directory = FSDirectory.open(new File(PATH_OF_INDEX));  
  86.             //由于Lucene2.9之后,其索引的格式就不会再兼容Lucene的所有版本了,所以在创建索引前,要指定其所匹配的Lucene版本号  
  87.             //这里通过IndexWriterConfig()构造方法的Version.LUCENE_36参数值指明索引所匹配的版本号,并使用了Lucene的标准分词器  
  88.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36)));  
  89.             for(File file : new File(PATH_OF_FILE).listFiles()){  
  90.                 doc = new Document();  
  91.                 //把内容添加到索引域中,即为该文档存储信息,供将来搜索时使用(下面的写法,其默认为Field.Store.NO和Field.Index.ANALYZED)  
  92.                 //如果我们想把content的内容也存储到硬盘上,那就需要先把file转换成字符串,然后按照"fileName"的存储方式加到Field中  
  93.                 //我们可以用commons-io-2.3.jar提供的FileUtils.readFileToString(file),这是很方便的工具包,有了它几乎都不用手写任何的IO方法了  
  94.                 //doc.add(new Field("content", FileUtils.readFileToString(file), Field.Store.YES, Field.Index.ANALYZED));  
  95.                 doc.add(new Field("content"new FileReader(file)));  
  96.                 //Field.Store.YES-----------这里是将文件的全名存储到硬盘中  
  97.                 //Field.Index.NOT_ANALYZED--这里是不对文件名进行分词  
  98.                 doc.add(new Field("fileName", file.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));  
  99.                 doc.add(new Field("filePath", file.getAbsolutePath(), Field.Store.YES, Field.Index.NOT_ANALYZED));  
  100.                 //通过IndexWriter添加文档到索引中  
  101.                 writer.addDocument(doc);  
  102.             }  
  103.         }catch(Exception e){  
  104.             System.out.println("创建索引的过程中遇到异常,堆栈轨迹如下");  
  105.             e.printStackTrace();  
  106.         }finally{  
  107.             if(null != writer){  
  108.                 try {  
  109.                     writer.close(); //IndexWriter在用完之后一定要关闭  
  110.                 } catch (IOException ce) {  
  111.                     System.out.println("关闭IndexWriter时遇到异常,堆栈轨迹如下");  
  112.                     ce.printStackTrace();  
  113.                 }   
  114.             }  
  115.         }  
  116.     }  
  117.       
  118.       
  119.     /** 
  120.      * 搜索文件 
  121.      * @see 1、创建Directory 
  122.      * @see 2、创建IndexReader 
  123.      * @see 3、根据IndexReader创建IndexSearcher 
  124.      * @see 4、创建搜索的Query 
  125.      * @see 5、根据searcher搜索并返回TopDocs 
  126.      * @see 6、根据TopDocs获取ScoreDoc对象 
  127.      * @see 7、根据searcher和ScoreDoc对象获取具体的Document对象 
  128.      * @see 8、根据Document对象获取需要的值 
  129.      * @see 9、关闭IndexReader 
  130.      */  
  131.     public void searchFile(){  
  132.         IndexReader reader = null;  
  133.         try{  
  134.             reader = IndexReader.open(FSDirectory.open(new File(PATH_OF_INDEX)));  
  135.             IndexSearcher searcher = new IndexSearcher(reader);  
  136.             //创建基于Parser搜索的Query,创建时需指定其"搜索的版本,默认搜索的域,分词器"....这里的域指的是创建索引时Field的名字  
  137.             QueryParser parser = new QueryParser(Version.LUCENE_36, "content"new StandardAnalyzer(Version.LUCENE_36));  
  138.             Query query = parser.parse("java");       //指定==>搜索域为content(即上一行代码指定的"content")中包含"java"的文档  
  139.             TopDocs tds = searcher.search(query, 10); //第二个参数指定搜索后显示的条数,若查到5条则显示为5条,查到15条则只显示10条  
  140.             ScoreDoc[] sds = tds.scoreDocs;           //TopDocs中存放的并不是我们的文档,而是文档的ScoreDoc对象  
  141.             for(ScoreDoc sd : sds){                   //ScoreDoc对象相当于每个文档的ID号,我们就可以通过ScoreDoc来遍历文档  
  142.                 Document doc = searcher.doc(sd.doc);  //sd.doc得到的是文档的序号  
  143.                 System.out.println(doc.get("fileName") + "[" + doc.get("filePath") + "]"); //输出该文档所存储的信息  
  144.             }  
  145.         }catch(Exception e){  
  146.             System.out.println("搜索文件的过程中遇到异常,堆栈轨迹如下");  
  147.             e.printStackTrace();  
  148.         }finally{  
  149.             if(null != reader){  
  150.                 try {  
  151.                     reader.close();  
  152.                 } catch (IOException e) {  
  153.                     System.out.println("关闭IndexReader时遇到异常,堆栈轨迹如下");  
  154.                     e.printStackTrace();  
  155.                 }  
  156.             }  
  157.         }  
  158.     }  
  159. }  

测试时,要在myExample/01_file/文件夹中准备几个包含内容的文件(比如txt格式的)

然后先执行createIndex()方法,再执行searchFile()方法,最后观看控制台输出即可


0 0
原创粉丝点击