lucene(索引的建立)
2017-04-15 00:48
381 查看
lucene的使用(索引的创建)
索引过程的核心类: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段[b]强制合并已删除的文档(清空回收站)这样就不能恢复了
[/b]
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);
索引创建的过程分析图
索引建立的简单步骤
创建Directory
Directory directory = FSDirectory.open(new File("索引文件存放的位置"));
注:此处使用的是FSDirectory是存放在磁盘上的,还有一种是RAMDirectory是存放在内存中的,但是没有办法持久化,所以推荐使用FSDirectory
创建IndexWriter
IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig( Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));//StandardAnalyzer标准分词器
分词(分词器核心)
AnalyzerSimpleAnalyzer(简单分词)、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
(将分词的语汇单元,进行各种各样过滤)
补充:自定义分词(以stop分词举例)
说明:现在都是用的是中文分词,jar包是:
<dependency> <groupId>com.janeluo</groupId> <artifactId>ikanalyzer</artifactId> <version>2012_u6</version> </dependency> //java中创建分词: Analyzer anal=new IKAnalyzer(true);
创建文档并且添加索引
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();
索引域选项
使用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之后添加了数字域来完成数字和日期的索引
相关文章推荐
- 用lucene为数据库搜索建立增量索引
- 使用lucene建立索引
- 用dotLucene为数据库内容建立索引
- 自己用LUCENE建立索引
- lucene3.5学习笔记02--创建索引和建立搜索
- lucene对数据库建立索引
- Lucene4.10使用教程(二):简单的索引建立和读取步骤(HelloLucene)
- 使用Lucene为数据库建立索引
- 用Lucene[1].net对数据库建立索引及搜索+
- 用Lucene.net对数据库建立索引及搜索<转>
- lucene3.0全站搜索建立索引时的编码处理
- lucene_建立索引
- lucene 4.6 为数据库建立增量索引
- lucene入门-复杂索引建立
- Lucene 2.0 建立索引 与 1.4区别
- 每日一练 Lucene3.5 建立索引
- lucene实时建立索引--注意事项
- Lucene2.9.2 + 盘古分词2.3.1(一) 入门: 建立简单索引,搜索(原创)
- 使用Lucene建立索引
- 用Lucene.net对数据库建立索引及搜索2