您的位置:首页 > 编程语言 > Java开发

自己动手写搜索引擎(常搜吧历程二#索引#)(Java、Lucene、hadoop)

2013-03-17 15:42 519 查看
Lucene的核心索引类:

1、IndexWriter:建立索引的核心组件。

2、Directory:代表一个lucene索引项的位置。

3、Analyzer:对文本内容进行分析的抽象类,具体实现中有停用词切除 、词干分析、大小写切换等功能。

4、Document:可以视作文本经过处理后所对应的对象,由多个字段组成 ,如路径、标题、摘要、修改日期等等。

5、Field:字段 ,对应于文本的某一部分数据,便于检索时根据结果提取。早期版本分为四个类型:Keyword、UnIndexed、UnStored和Text,其主要区别归结于三个方面:是否被分析,是否被索引,是否存储于索引中。但是在最新版本的Lucene中,使用了一种更为统一的形式,也即只有Field一个类,然后使用一些参数来描述这个字段的属性,通过参数组合,可以组合出各种类别,甚至那四种不存在的类别理论上也是可以组合出来。

public Field (String name, String value, Store store, Index index)

下面来看一个例子代码:

package com.qianyan.luceneIndex;

import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class IndexTest {

public static void main(String[] args) throws IOException{

String[] ids = {"1", "2", "3"};
String[] names = {"zhangsan", "lisi", "wangwu"};
String[] addresses = {"shanghai", "beijing", "guangzhou"};
Analyzer analyzer = new StandardAnalyzer();
String indexDir = "E:/luceneindex";
Directory dir = FSDirectory.getDirectory(indexDir);
//true 表示创建或覆盖当前索引;false 表示对当前索引进行追加
//Default value is 128
IndexWriter writer = new IndexWriter(dir, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
for(int i = 0; i < ids.length; i++){
Document document = new Document();
document.add(new Field("id", ids[i], Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("name", names[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("address", addresses[i], Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(document);
}
writer.optimize();
writer.close();
}

}
运行后查看 E:/luceneindex 会看到生成的索引文件。

删除索引:

package com.qianyan.luceneIndex;

import java.io.IOException;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class TestDelDocument {

public static void main(String[] args) throws IOException{
String indexDir = "E:/luceneindex";
Directory dir = FSDirectory.getDirectory(indexDir);
IndexReader reader = IndexReader.open(dir);
System.out.println(reader.maxDoc());
//直接根据序号删除索引 注:从0开始
//reader.deleteDocument(0);
//根据索引值名删除索引
//reader.deleteDocuments(new Term("id", "3"));
System.out.println(reader.numDocs());
reader.close();
dir.close();
}
}


取消删除标记索引:

package com.qianyan.luceneIndex;

import java.io.IOException;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class UnDeleteDocument {

public static void main(String[] args) throws IOException {
String indexDir = "E:/luceneindex";
Directory dir = FSDirectory.getDirectory(indexDir);
IndexReader reader = IndexReader.open(dir);

System.out.println("before delete:" + reader.numDocs());

reader.deleteDocuments(new Term("id", "1"));
System.out.println("after delete:" + reader.numDocs());

reader.undeleteAll();
System.out.println("after undelete:" + reader.numDocs());

reader.close();
dir.close();

}
}


修改索引(注:在lucene里修改意味着 删除后添加)

package com.qianyan.luceneIndex;

import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class UpdateDocument {

public static void main(String[] args) throws IOException{
Analyzer analyzer = new StandardAnalyzer();
String indexDir = "E:/luceneindex";
Directory dir = FSDirectory.getDirectory(indexDir);
IndexReader reader = IndexReader.open(dir);

System.out.println("before delete : " + reader.numDocs());
reader.deleteDocuments(new Term("id", "2"));
System.out.println("after delete : " + reader.numDocs());
reader.close();

IndexWriter writer = new IndexWriter(dir, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);
Document document = new Document();
document.add(new Field("id", "2", Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("name", "Tom", Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("address", "tianjin", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(document);
writer.close();

reader = IndexReader.open(dir);
System.out.println("after add : " + reader.numDocs());

dir.close();
reader.close();
}
}


在lucene中搜索算法的score简单说是由 tf * idf * boost * lengthNorm计算得来的。

tf:是查询的词在文档中出现的次数的平方根

idf:表示反转文档频率。

boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值lengthNorm,是由搜索的field的长度决定了,越长文档的分值越低。

控制score的就是设置boost值。

lucene会把计算后,最大分值超过1.0的分值作为分母,其他的文档的分值都除以这个最大值,计算出最终的得分。

document.setBoost(0.5f); //不太重要

document.setBoost(1.5f); //比较重要

field.setBoost(0.5f); //不太重要

field.setBoost(1.5f); //比较重要

lucene索引效率设置:

setMaxBufferedDocs 16MB

setMergeFactor 10

setMaxMergeDocs Inter.Max_VALUE;

Directory dir = FSDirectory.getDirectory(indexDir); //文件系统读取,IO操作

Directory dir = RAMDirectory(); //内存读取,效率高,容量小
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐