Lucene基础(二)--索引的操作
索引的操作
我们建立所有就是要达到快速检索的目的,对数据能够方面便的查找,和数据库类似,索引也有自己的相关增删改查的操作。
在索引的增删改查中,增删改属于写操作,主要是有IndexWrite提供的方法处理;而查显而易见,读操作,使用IndexSeacher 提供的方法来实现。在Lucene的官方文档找到 org.apache.lucene.index.IndexWriter 这个类,我们就可以看到他很多方法。
创建索引
如同上一章里面的代码,创建索引时先建立文件,创建索引的域,再使用IndexWriter的addDocument()方法就可以了,核心代码如下:
iwriter = new IndexWriter(directory, new IndexWriterConfig(version, new StandardAnalyzer(version)));
for(String text : content){ doc = new Document();
//使用的field 有很多类型,理解他们的区别 例如:TextField 和 StringField等
doc.add(new TextField("content", text,Field.Store.YES));
iwriter.addDocument(doc);
}
索引删除
索引删除包括只删除索引下面的document和删除索引文件
在IndexWriter有如下一些方法
- deleteAll() 删除索引中所有的documents
- deleteDocuments(Query… queries) 按照提供的Query 删除documents
- deleteDocuments(Term… terms) 按照短语删除documents
- deleteUnusedFiles() 删除所有不再使用index的文件
- forceMergeDeletes() 删除处于已经删除的状态documents,由此可见,之前的删除文档的方法并没有真正的删除掉的documents,只是标记删除,我个人理解是类似逻辑上的删除
- forceMergeDeletes(boolean doWait) 删除过程中指明是否阻塞,直到操作完成
索引更新
更新操作也是一样,查看文档就有,这里截个图:
索引查询
Query
索引查询的时候可以使用Query的实现子类来创建查询,执行IndexSearcher的search方法来查询,也可以使用QueryParse类来构造查询.
分页
- 方式1:在scoreDoc中进行分页,数据一次性查出来,在结果集分页,结果集较大时容易溢出
- 方式2:使用searcheAfter,等价查询的次数,但是不会出现查询结果溢出,推荐,类似数据库中的分页查询
这个类似数据库中的查询,可以对结果集分页显示,类似方式一,查询的时候直接分页,类似方式二 。
索引操作实例
package lucene_demo03;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
/**
*
* 关于索引的查询(分页查询) 方式1:在scoreDoc中进行分页,数据一次性查出来,在结果集分页,结果集较大时容易溢出
* 方式2:使用searcheAfter,等价查询的次数,但是不会出现查询结果溢出,推荐,类似数据库中的分页查询
*
* @author YipFun
*/
public class LuceneDemo03
{
private static final Version version = Version.LUCENE_4_9;
private Directory directory = null;
private DirectoryReader ireader = null;
private IndexWriter iwriter = null;
// 测试数据
private String[] content = { "hello lucene", "I love coding", "I can play basketball", "I can play football", "I can play dota" };
/**
* 构造方法
*/
public LuceneDemo03()
{
directory = new RAMDirectory();
}
/**
* 创建索引
*/
public void createIndex()
{
Document doc = null;
try
{
iwriter = new IndexWriter(directory, new IndexWriterConfig(version, new StandardAnalyzer(version)));
for (String text : content)
{
doc = new Document();
// 使用的field 有很多类型,理解他们的区别 例如:TextField 和 StringField
doc.add(new TextField("content", text, Field.Store.YES));
iwriter.addDocument(doc);
}
} catch (IOException e)
{
e.printStackTrace();
} finally
{
try
{
if (iwriter != null)
iwriter.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
public IndexSearcher getSearcher()
{
try
{
if (ireader == null)
{
ireader = DirectoryReader.open(directory);
} else
{
DirectoryReader tr = DirectoryReader.openIfChanged(ireader);
if (tr != null)
{
ireader.close();
ireader = tr;
}
}
return new IndexSearcher(ireader);
} catch (CorruptIndexException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
/**
*
* @param field
* @param term
* @param num
*/
public void searchByTerm(String field, String term, int num)
{
IndexSearcher isearcher = getSearcher();
// 注意query的实现类和QueryParse的用法的区别
TermQuery query = new TermQuery(new Term(field, term));
ScoreDoc[] hits;
try
{
// 注意searcher的几个方法
hits = isearcher.search(query, null, num).scoreDocs;
// Iterate through the results:
for (int i = 0; i < hits.length; i++)
{
Document hitDoc = isearcher.doc(hits[i].doc);
System.out.println("This is the text to be indexed=" + hitDoc.get("content"));
}
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 区别与上一种查询,使用QueryParser的parse方法构造一个Query传递给方式使用
*
* @param query
* @param num
*/
public void searchByQueryParse(Query query, int num)
{
try
{
IndexSearcher searcher = getSearcher();
TopDocs tds = searcher.search(query, num);
System.out.println("一共查询了:" + tds.totalHits);
for (ScoreDoc sd : tds.scoreDocs)
{
Document doc = searcher.doc(sd.doc);
System.out.println("This is the text to be indexed=" + doc.get("content"));
}
} catch (CorruptIndexException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 第一中分页方式,对ScoreDoc进行分页
*
* @param query
* @param pageIndex
* 从1开始,即第一页
* @param pageSize
* 分页大小
* @param num
* search top n hits
*/
public void searchForPage(Query query, int pageIndex, int pageSize, int num)
{
try
{
IndexSearcher searcher = getSearcher();
TopDocs tds = searcher.search(query, num);
System.out.println("一共查询了:" + tds.totalHits);
// 对ScoreDoc分页
int start = (pageIndex - 1) * pageSize;
int end = pageIndex * pageSize;
ScoreDoc scoreDocs[] = tds.scoreDocs;
for (int i = start; i < end; i++)
{
Document doc = searcher.doc(scoreDocs[i].doc);
System.out.println("This is the text to be indexed=" + doc.get("content"));
}
} catch (CorruptIndexException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 使用searchAfter 实现在查询的时候的分页
*
* @param query
* @param pageIndex
* @param pageSize
* @throws IOException
*/
public void searchForPageByAfter(Query query, int pageIndex, int pageSize) throws IOException
{
IndexSearcher searcher = getSearcher();
// 先获取上一页的最后一个元素
ScoreDoc lastSd = getLastScoreDoc(pageIndex, pageSize, query, searcher);
TopDocs tds = searcher.searchAfter(lastSd, query, pageSize);
for (ScoreDoc sd : tds.scoreDocs)
{
Document doc = searcher.doc(sd.doc);
System.out.println("This is the text to be indexed=" + doc.get("content"));
}
}
/**
* 返回分页查询的上一条
*
* @param pageIndex
* @param pageSize
* @param query
* @param indexSearcher
* @return
*/
private ScoreDoc getLastScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher searcher)
{
if (pageIndex == 1)
return null;// 如果是第一页就返回空
int num = pageSize * (pageIndex - 1);// 获取上一页的数量
TopDocs tds = null;
try
{
tds = searcher.search(query, num);
} catch (IOException e)
{
e.printStackTrace();
}
return tds.scoreDocs[num - 1];
}
public static void main(String[] args) throws ParseException, IOException
{
LuceneDemo03 ld = new LuceneDemo03();
ld.createIndex();
ld.searchByTerm("content", "play", 500);
System.out.println("==============1======================");
QueryParser parser = new QueryParser(version, "content", new StandardAnalyzer(version));
Query q = parser.parse("play");// 研究下parse的语法
ld.searchByQueryParse(q, 500);
System.out.println("===============2=====================");
ld.searchForPage(q, 1, 2, 500);// 从第一页开始
System.out.println("================3====================");
ld.searchForPageByAfter(q, 1, 2);// 从第一页开始
System.out.println("================4====================");
}
}
Lucene基础(二)--索引的操作的更多相关文章
- 基础DOM和CSS操作(二)
元素样式操作 元素样式操作包括了直接设置CSS样式.增加CSS类别.类别切换.删除类别这几种操作方法.而在整个jQuery使用频率上来看,CSS样式的操作也是极高的,所以需要重点掌握. CSS操作方法 ...
- 01 lucene基础 北风网项目培训 Lucene实践课程 索引
在创建索引的过程中IndexWriter会创建多个对应的Segment,这个Segment就是对应一个实体的索引段.随着索引的创建,Segment会慢慢的变大.为了提高索引的效率,IndexWrite ...
- oracle 基础知识(十二)----索引
一, 索引介绍 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是一个独立于 ...
- day 70 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- day 56 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- Lucene基础(2)
上一篇:Lucene基础(1) 一.Lucene术语 Document, Field, Term, Query, Analyzer相信在其中大多数在之前已经理解了...对其中部分概念详细说明 Docu ...
- Lucene基础(1)
下一篇: Lucene基础(2) 一.Lucene介绍 http://www.kailing.pub/index/columns/colid/16.html Documentation:http:// ...
- Python全栈开发【基础二】
Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...
- Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档
array,list,dataframe索引切片操作 2016年07月19日——智浪文档 list,一维,二维array,datafrme,loc.iloc.ix的简单探讨 Numpy数组的索引和切片 ...
随机推荐
- linux实例 批量修改图片文件名
1.如10.11一批这样的目录,10.11 10.12等等 然后里面的图片.jpg文件要修改成对应的日期.jpg,也就是说 编程1011.jpg这样的文件名 示例如下: #!/bin/bashfor ...
- C# 之 Word光标移动 GoTo 方法
对于 Document 或 Range对象:返回一个 Range对象,该对象代表指定项(例如页.书签或域)的开始位置. 对于 Selection对象:将插入点移至指定项前面的字符位置,并返回一个 Ra ...
- Spring中Bean的生命中期与InitializingBean和DisposableBean接口
Spring提供了一些标志接口,用来改变BeanFactory中的bean的行为.它们包括InitializingBean和DisposableBean.实现这些接口将会导致BeanFactory调用 ...
- [转]ASP.NET MVC 2: Model Validation
本文转自:http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx?CommentPo ...
- 关于XML的Schema文件讲解
1 Schema概述 1.1 什么是Schema l Schema是新的XML文档约束:DTD出现的比较早. l Schema要比DTD强大很多: l Schema本身也是XML文档,但Sche ...
- Android开发了解——AIDL
AIDL:Android Interface Definition Language,即Android接口定义语言. 什么是AIDL Android系统中的进程之间不能共享内存,因此,需要提供一些机制 ...
- PHP 使用get_class_methods()和array_diff() 兩個相同的類中方法差集
进行二次开发时,习惯一份是原封不动的,一份正在修改.在修改时,发现修改的缺少原项目中的一些方法.本打算一个方法一个方法的对比,可是这样会比较花时间,划不来,PHP可以使用get_class_metho ...
- 本地缓存下载文件,download的二次封装
来源:http://ask.dcloud.net.cn/article/524 源码下载链接 说明: (1)由于平时项目中大量用到了附件下载等功能,所以就花了一个时间,把plus的downlaod进行 ...
- apache ambari web页面无法访问解决办法
ambari-server启动成功,但是页面无法访问 作者:Bo liang链接:http://www.zhihu.com/question/34405898/answer/115001510来源:知 ...
- Sql Server通过BCP数据导出Excel
1.1. bcp的主要参数介绍 bcp共有四个动作可以选择. (1) 导入. 这个动作使用in命令完成,后面跟需要导入的文件名. (2) 导出. 这个动作使用out命令完成,后面跟需要导出的文件名. ...