【Lucene学习笔记】基本的索引与检索
Lucene作为全文检索工具,其作用还是蛮大的。举个例子,像我专门腾个盘来放各种各样的文档,都有50多个G了,现在有些啥文档、都存在哪的,我自己都记不清楚许多了- -Windows自带了搜索的,可是我只知道它能用来检索某个文件名,前提是我得记得住文件名啊!而且平时我们那会关心文件名,我们更关心内容是否符合我们要找的东西,只不过一般标题和正文都是匹配的而已。在这种情况下还不如自己用用Lucene来建个索引,当然索引文件也是要占空间的- -
接下来就先看看一个最基本的索引与检索,以后的内容就是在这个框架上不断补充和深化。最近Lucene4.0正式版发布了,但是文档半天看不懂- -还是先用着3.6吧,等着研究清楚了再说。说实话,这东西我还真不知道该怎么说明,所以就贴出代码,然后注释吧。
1 import java.io.*; 2 import java.util.Scanner; 3 4 import org.apache.lucene.index.*; 5 import org.apache.lucene.queryParser.ParseException; 6 import org.apache.lucene.queryParser.QueryParser; 7 import org.apache.lucene.search.*; 8 import org.apache.lucene.store.*; 9 import org.apache.lucene.util.Version; 10 import org.apache.lucene.analysis.standard.StandardAnalyzer; 11 import org.apache.lucene.document.*; 12 13 public class TestLucene { 14 public static void main(String[] args){ 15 Directory dir=null; 16 /** 17 * 建立索引 18 */ 19 IndexWriter iw=null; 20 try { 21 //1.创建Directory对象 22 //.指定你要将索引创建在哪个路径。我是Eclipse创建的项目,所以用的相对路径 23 //.值得注意的是,貌似new一个和调用open方法都可以,但我建议open,这样毕竟会有些处理和判断的,可以看一下源码它们的区别 24 dir=FSDirectory.open(new File("index")); 25 //2.创建IndexWriter对象 26 //.用来生成索引。在3.6中专门分出个IndexWriterConfig来配置IndexWriter 27 //.不知道哪个版本之前是直接传参数给IndexWriter构造函数,这样就很繁琐,参数一大串,重载构造函数一大堆,于是重构了一下 28 IndexWriterConfig conf=new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36)); 29 iw = new IndexWriter(dir, conf); 30 31 //指定你要索引的文件目录,文件不止一个,需要为每个文件都添加索引,自然得循环 32 //你也可以用高级点的语法:for(File f:file),相当于foreach。我也不知道是java几有的,反正我是java7 33 File file=new File("file"); 34 for(int i=0;i<file.listFiles().length;i++){ 35 System.out.println("建立文件"+i+"的索引"); 36 File f=file.listFiles()[i]; 37 //3.创建Document对象 38 Document doc=new Document(); 39 //4.为Document配置Field 40 //.Document就相当于数据库中的一个元祖,而Field就是列,整个索引自然是一张表 41 //.这里分成三列,文件名、路径和内容。路径和文件名也要存储在索引中,而且它们是一个整体,不用分词 42 //.如果要用4.0,Field也是重构了的,比如内容可用TextField,后面两个则StringField。而这几个重载构造函数自然被弃用了 43 //.而且4.0的域存储选项和域索引选项貌似不见了,我也还不清楚到哪去了 44 45 // BufferedReader input = new BufferedReader(new FileReader(file)); 46 // StringBuffer buffer = new StringBuffer(); 47 // String text; 48 // while((text=input.readLine())!=null){ 49 // buffer.append(text +"/n"); 50 // } 51 // doc.add(new Field("name",buffer.toString(),Field.Store.YES,Field.Index.ANALYZED)); 52 53 doc.add(new Field("contents",new FileReader(f))); 54 doc.add(new Field("name",f.getName(),Field.Store.YES,Field.Index.ANALYZED)); 55 doc.add(new Field("path",f.getAbsolutePath(),Field.Store.YES,Field.Index.NOT_ANALYZED)); 56 //5.通过IndexWriter将文档添加到索引 57 iw.addDocument(doc); 58 } 59 } catch (FileNotFoundException e) { 60 e.printStackTrace(); 61 } catch (IOException e) { 62 e.printStackTrace(); 63 }finally{ 64 System.out.println("建立索引完毕"); 65 //8.关闭IndexWriter流 66 //.本来我还关闭Directory的,但是运行异常,原因我不清楚 67 try { 68 if(iw!=null){ 69 iw.close(); 70 } 71 } catch (IOException e) { 72 e.printStackTrace(); 73 } 74 } 75 76 /** 77 * 查询索引 78 */ 79 System.out.print("请输入检索词:"); 80 Scanner input=new Scanner(System.in); 81 String qstr=input.nextLine(); 82 83 IndexReader ir=null; 84 IndexSearcher srch=null; 85 try { 86 //1.创建Directory 87 //.还是你索引所在的目录,毕竟是在索引中检索 88 dir=FSDirectory.open(new File("index")); 89 //2.创建IndexReader 90 //.Writer是写到索引文件中去,Reader自然是从索引文件中把内容读出来 91 ir=IndexReader.open(dir); 92 //3.根据IndexReader创建IndexSearch 93 //.就是要在这些索引中查找 94 srch=new IndexSearcher(ir); 95 //4.创建搜索的Query 96 //.首先得创建一个Parser对象,你输入的检索关键词也得解析解析吧,搜索域设定在contents中,也就是内容中有才算数,免得文不对题 97 QueryParser parser=new QueryParser(Version.LUCENE_36, "contents", new StandardAnalyzer(Version.LUCENE_36)); 98 Query query=parser.parse(qstr); 99 //5.根据Search搜索并返回TopDocs的文档100 //.这就开始执行搜索,搜索整个索引库后排序,然后取前3条,当然这里总共也只有3条索引101 TopDocs tds=srch.search(query, 3);102 //6.根据TopDocs获取ScoreDoc103 //.ScoreDoc的下标就相当于每个文档的id号,因为返回值是根据得分从高到低排序了的,直接根据它来遍历显示就OK了104 ScoreDoc[] sds=tds.scoreDocs;105 for(int i=0;i<sds.length;i++){106 //7.根据Searcher和ScoreDoc获取具体Document107 Document doc=srch.doc(sds[i].doc);108 //8.根据Document获取需要的值109 System.out.println(doc.get("name")+" | "+doc.get("path"));110 }111 } catch (IOException e) {112 e.printStackTrace();113 }catch(ParseException e){114 e.printStackTrace();115 }finally{116 try {117 if(ir!=null){118 ir.close();119 }120 if(srch!=null){121 srch.close();122 }123 } catch (IOException e) {124 e.printStackTrace();125 }126 }127 }128 }
最后的执行结果是:
TAG: