索引过程的核心类:IndexWriter,Directory,Analyzer,Document,Field
准备的jar包:
<dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>3.5.0</version> </dependency>首先提供简单的索引创建实例,代码如下:
Directory directory = FSDirectory.open(new File("索引文件存放的位置")); IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35))); File file = new File("d:/lucene/example");// 此处作者使用的是本地的文件作为数据 Document doc = null; Random ran = new Random(); int index = 0; for (File f : file.listFiles()) { int score = ran.nextInt(600); doc = new Document(); doc.add(new Field("id", String.valueOf(index++), Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS)); doc.add(new Field("content", new FileReader(f))); doc.add(new Field("filename", f.getName(), Field.Store.YES,Field.Index.NOT_ANALYZED)); doc.add(new Field("path", f.getAbsolutePath(), Field.Store.YES,Field.Index.NOT_ANALYZED)); doc.add(new NumericField("date", Field.Store.YES, true).setLongValue(f.lastModified())); doc.add(new NumericField("size", Field.Store.YES, true).setIntValue((int) (f.length()))); doc.add(new NumericField("score", Field.Store.NO, true).setIntValue(score)); writer.addDocument(doc); } writer.close();索引的删除
// 如果重新创建,则删除之前的内容 writer.deleteAll(); writer.deleteDocuments(new Term("id","1")); 索引的恢复 // 使用IndexReader进行恢复 IndexReader reader = IndexReader.open(directory, false); // 恢复时,必须把IndexReader的只读?readOnly)设置为false reader.undeleteAll(); reader.close(); 合并段信息 writer.forceMerge(1);//合并为1段 强制合并已删除的文档(清空回收站)这样就不能恢复了 writer.forceMergeDeletes(); 索引的更新 Document doc = new Document(); doc.add(new Field("id", "11", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); doc.add(new Field("email", "test" + emails[0] + "@test.com", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.add(new Field("content", contents[0], Field.Store.NO, Field.Index.ANALYZED)); doc.add(new Field("name", names[0], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); // 存储数字 doc.add(new NumericField("attach", Field.Store.YES, true) .setIntValue(attachs[0])); // 存储日期 doc.add(new NumericField("date", Field.Store.YES, true) .setLongValue(dates[0].getTime())); writer.updateDocument(new Term("id", "1"), doc);索引创建的过程分析图
Analyzer
SimpleAnalyzer(简单分词)、StopAnalyzer(停用词分词)、WhitespaceAnalyzer(空格符分词)、StandardAnalyzer(标准分词)
TokenStream分词器做好处理之后得到的一个流,这个流中存储了分词的各种信息,可以通过TokenStream有效的获取到分词单元信息
生成的流程:
tokenStream里面存储的值(存储值代码核心)
Analyzer a = new StandardAnalyzer(Version.LUCENE_35);//此处使用的是标准分词 TokenStream stream = a.tokenStream("content", new StringReader(str)); // 位置增量的属性,存储语汇单元之间的距离 PositionIncrementAttribute pia = stream.addAttribute(PositionIncrementAttribute.class); // 每个语汇单元的位置的偏移量 OffsetAttribute oa = stream.addAttribute(OffsetAttribute.class); // 存储每一个语汇单元的信息(分词单元信息) CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class); // 使用的分词器的类型信息 TypeAttribute ta = stream.addAttribute(TypeAttribute.class); for (; stream.incrementToken();) { System.out.print(pia.getPositionIncrement() + "="); System.out.println(cta + "[" + oa.startOffset() + "-"+ oa.endOffset() + "-type-" + ta.type() + "\n"); }在这个流中所需要存储的数据
Tokenizer
作用:主要负责接收字符流Reader,将Reader进行分词操作。有如下一些实现类
TokenFilter
(将分词的语汇单元,进行各种各样过滤)
说明:现在都是用的是中文分词,jar包是:
<dependency> <groupId>com.janeluo</groupId> <artifactId>ikanalyzer</artifactId> <version>2012_u6</version> </dependency> //java中创建分词: Analyzer anal=new IKAnalyzer(true);使用Field.Index.*来进行操作
Index.ANALYZED:进行分词和索引,适用于标题、内容等
Index.NOT_ANALYZED:进行索引,但是不进行分词,如果身份证号,姓名,ID等,适用于精确搜索
Index.ANALYZED_NOT_NORMS:进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息
Index.NOT_ANALYZED_NOT_NORMS:即不进行分词也不存储norms信息
Index.NO:不进行索引
Field.Store.*
YES:将会存储域值,原始字符串的值会保存在索引,以此可以进行相应的恢复操作,对于主键,标题可以是这种方式存储
NO:不会存储域值,通常与Index.ANAYLIZED合起来使用,索引一些如文章正文等不需要恢复的文档
补充:
1、对数字进行索引可以使用分词器进行不同的索引
·WhitespaceAnalyzer和StandardAnalyzer会索引数字
·SimpleAnalyzer和StopAnalyzer不会索引数字
2、在3.0之后添加了数字域来完成数字和日期的索引
