您的位置:首页 > 运维架构

3.创建和维护索引库(Lucene6.0.0 CRUD)

2017-05-21 21:32 239 查看
项目源码:https://github.com/tangxing1993/lucene

3.1 创建和更新索引

Lucene给我们提供了创建和更新索引的API,在生成索引的过程中涉及到以下几个类。
IndexWriter>Document>Field>Analyzer
Field 域对象,存在与文档内。通用接口IndexField,field是一个抽象域对象。StringField不分词完全存入到索引库中,TextField 进行分词,并且索引


创建索引

索引一般存放在硬盘的某个路径下,我们可以使用IndexWriter来创建一个索引库,IndexWriter对象的相关参数有:索引路径和配置信息,创建完索引库后要把索引文档放入到索引库中,索引文档包含要索引的域信息。


/**
* 创建索引
*/
public void createIndex(){
long startTime = System.currentTimeMillis(); //索引的创建时间
System.out.println("start index ... ");
IndexWriter writer = null;
Document document = null;
try{
IndexWriterConfig config = new IndexWriterConfig(analyzer);
writer  = new IndexWriter(directory, config);
writer.deleteAll();
/**
* 这里为了提高索引的速度,我们重用field对象,而不是每次创建新的,可以节省GC的消耗时间
* Field是intPoint/StringField/TextField/longPoint等的父类
* 我们可以根据数据类型的需要选择合适的field对象
*/
IntPoint iPoint = new IntPoint("id", 0);
StringField sField = new StringField("name","", Store.YES);
TextField tField = new TextField("content", "", Store.YES);
LongPoint lPoint = new LongPoint("date", 0);
for(int i=0;i<ids.length;i++){
document = new Document();
iPoint.setIntValue(ids[i]);
document.add(iPoint);
sField.setStringValue(names[i]);
document.add(sField);
tField.setStringValue(contents[i]);
document.add(tField);
lPoint.setLongValue(dates[i].getTime());
document.add(lPoint);
writer.addDocument(document);
}
long endTime = System.currentTimeMillis();//索引的结束时间
System.out.println("end index !!!");
System.out.println("times:"+(endTime-startTime)+"ms");
}catch(Exception e){
e.printStackTrace();
}finally{
if(null!=writer){
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}






更新索引

Lucene更新索引文档是先删除旧的文档信息,然后把新的文档写入到索引库中。用到的方法是IndexWriter.updateDocument,传入的参数为term,要删除的文档term信息,第二个参数为新的文档信息


/**
* 更新索引对象  早期的版本中先通过IndexReader删除文档 再使用IndexWriter写入更新后的文档
* 新版本中我们可以通过先查找出要修改的旧文档,然后改变要改动的列,最后updateDocument
*/
public void updateIndex(){
IndexWriter writer = null;
Document document = null;
try{
System.out.println("开始更新...");
writer = new IndexWriter(directory,new IndexWriterConfig(analyzer));
IndexSearcher search = new IndexSearcher(this.getIndexReader());
Query query = new QueryParser("name", analyzer).parse("aa");
TopDocs topDocs = search.search(query, 10);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
if(scoreDocs.length==0){
throw new IllegalArgumentException("索引中没有匹配结果...");
}else if(scoreDocs.length>1){
throw new IllegalArgumentException("索引匹配多个结果...");
}else{
//获取旧文档
document = search.doc(scoreDocs[0].doc);
//先删除要改变的旧列
document.removeFields("name");
document.add(new StringField("name","update",Store.YES));
//term是搜索语法的最小单位    这里的更新是先删除在更新  删除的对象放在索引回收站里面   数据还可以恢复
writer.updateDocument(new Term("name","aa"), document);
}
System.out.println("文档更新成功!");
}catch(Exception e){
e.printStackTrace();
}finally{
if(null!=writer){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


效果展示:





索引库的删除

lucene使用IndexWriter来删除索引文档


public void delete(){
IndexWriter writer =null;
try{
writer = new IndexWriter(directory, new IndexWriterConfig(analyzer));
//TermQuery  精确的查询方法
writer.deleteDocuments(new TermQuery(new Term("name", "bb")));
}catch(Exception e){
e.printStackTrace();
}finally{
if(null!=writer){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


效果展示:



简单的索引查询

Lucene使用IndexSearch来执行查询的所有操作,需要参数:索引库的字符流对象。lucene运用search方法查询出具有相关度的数据,然后我们按照评分取出。TopDocs具有相关度的文档,ScoreDocs文档评分数组


public void doSearch(){
IndexSearcher search = null;
try{
search = new IndexSearcher(this.getIndexReader());
//创建查询解析器
QueryParser parse = new QueryParser("content", analyzer);
//获取查询对象
Query query = parse.parse("like");
//搜索索引库返回最相关的10条数据
TopDocs topDocs = search.search(query, 10);//第二个参数为搜索显示的记录数
//从topDocs中取出查询结果
ScoreDoc[] sds = topDocs.scoreDocs;
for(ScoreDoc sd : sds){
//获取结果文档信息
Document doc = search.doc(sd.doc);
System.out.println("docID:"+sd.doc+" | id:"+doc.get("id")+" | "
+ "name:"+doc.get("name")+" | content:"+doc.get("content")+" | date:"+doc.get("date"));
}
}catch(Exception e){
e.printStackTrace();
}
}


结果:



通过结果发现。使用IntPoint和LongPoint并没有把数据存放到索引库中,所以查询到的结果为null

Field总结

IntPoint

索引int类型的值不存储不排序

FloatPoint

索引float类型的值不存储不排序

DoublePoint

索引Double类型的值不存储不排序

BinaryDocValuesField

只存储不共享,例如标题类字段,如果需要共享并排序,推荐使用

NumericDocValuesField

存储long型字段,用于评分、排序和值检索,如果需要存储值,还需要添加一个单独的StoredField实例

SortedDocValuesField

索引并存储,用于String类型的Field排序,需要在StringField后添加同名的SortedDocValuesField

StringField

只索引但不分词,所有的字符串会作为一个整体进行索引,例如通常用于country或id等

TextField

索引并分词,不包括term vectors,例如通常用于一个body Field

StoredField

存储Field的值,可以用 IndexSearcher.doc和IndexReader.document来获取存储的Field和存储的值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lucene