lucene(索引的建立)

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段
强制合并已删除的文档(清空回收站)这样就不能恢复了
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标准分词器

分词(分词器核心)

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

(将分词的语汇单元,进行各种各样过滤)

补充:自定义分词(以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、对数字进行索引可以使用分词器进行不同的索引

  ·WhitespaceAnalyzerStandardAnalyzer会索引数字

  ·SimpleAnalyzerStopAnalyzer不会索引数字

2、在3.0之后添加了数字域来完成数字和日期的索引


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值