??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
SimpleFSDirectory:FSDirectory的简单实?/span>,q发能力有限Q遇到多U程d一个文件时?x)遇到瓶颈,通常?/span>NIOFSDirectory?/span>MMapDirectory代替?/span>
NIOFSDirectoryQ通过java.nio's FileChannel实行定位dQ支持多U程读(默认情况下是U程安全的)(j)。该cM使用FileChannelq行L作,写操作则是通过FSIndexOutput实现?/span>
注意Q?/span>NIOFSDirectory 不适用?/span>WindowspȝQ另外如果一个访问该cȝU程Q在IOd时被interrupt?/span>cancelQ将?x)导致底层的文g描述W被关闭Q后l的U程再次讉KNIOFSDirectory时将?x)出?/span>ClosedChannelException异常Q此U情况应?/span>SimpleFSDirectory代替?/span>
MMapDirectoryQ通过内存映射q行读,通过FSIndexOutputq行写的FSDirectory实现cR用该cL要保证用_的虚拟地址I间。另外当通过IndexInput?/span>closeҎ(gu)q行关闭时ƈ不会(x)立即关闭底层的文件句柄,只有GCq行资源回收时才?x)关闭?/span>
Z(jin)能适应各个操作pȝ选择最?/span>DirectoryҎ(gu)Q?/span>lucene 提供FSDirectorycȝ?rn)态方?/span>open()实现自适应?/span>
public static FSDirectory open(File path, LockFactory lockFactory) throws IOException {
if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX)
&& Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
return new MMapDirectory(path, lockFactory);
} else if (Constants.WINDOWS) {
return new SimpleFSDirectory(path, lockFactory);
} else {
return new NIOFSDirectory(path, lockFactory);
}
}
RAMDirectoryQ常d存的Directory实现方式。默认通过SingleInstanceLockFactoryQ单实例锁工厂)(j)q行锁的实现?span style="color:red">该类不适合大量索引的情?/span>?span style="color:red">另外也不适用于多U程的情?/span>?/span> 在烦(ch)引数据量大的情况下徏议?/span>MMapDirectory代替?/span>RAMDirectory?/span>Directory抽象cd使用内存最为文件存储的实现c,其主要是所有的索引文g保存到内存(sh)。这样可以提高效率。但是如果烦(ch)引文件过大的话,则会(x)D内存?sh)Q因此,型的系l推荐用,如果大型的,索引文g辑ֈGU别上,推荐使用FSDirectory?/span>
NRTCachingDirectoryQ是?/span>RAMDirectory的封装,适用于近乎时Ӟnear-real-timeQ操作的环境?/span>
FileSwitchDirectory:文g切换?/span>Directory实现.针对lucene的不同的索引文g使用不同?/span>Directory .借助FileSwitchDirectory整合不同?/span>Directory实现cȝ优点于一w?/span>
比如MMapDirectory,借助内存映射文g方式提高性能Q但又要减少内存切换的可?/span> Q当索引太大的时候,内存映射也需要不断地切换Q这样优点也可能变缺点,而之前的NIOFSDirectory实现java NIO的方式提高高q发性能Q但又因高ƈ发也?x)导?/span>IOq多的媄(jing)响,所以这ơ可以借助FileSwitchDirectory发挥他们两的优点?/span>
RateLimitedDirectoryWrapper:通过IOContext来限制读写速率?/span>Directory装cR?/span>
CompoundFileDirectoryQ用于访问一个组合的数据?hu)。仅适用于读操作。对于同一D内扩展名不同但文g名相同的所有文件合q到一个统一?/span>.cfs文g和一个对应的.cfe文g内?/span>
.cfs文g?/span>HeaderQ?/span>FileData?/span>FileCountl成?/span>.cfe文g?/span>HeaderQ?/span>FileCount,FileName,DataOffset,DataLengthl成?/span>.cfs文g中存储着索引的概要信息及(qing)l合文g
的数目(FileCountQ?/span>.cfe文g存储文g目录的条目内容,内容中包括文件数据扇区的起始位置Q文件的长度?qing)文件的名称?/span>
TrackingDirectoryWrapperQ?/span>Directory的代理类。用于记录哪些文件被写入和删除?/span>
文章转蝲q来的!
?/span>2013q底公司接到一个项目用?/span>lucene,q是我第一ơ正真接?/span>LuceneQ代码比较?/span>3.6版本Q不适合新项目的需求(I间查询Q。于是下载了(jin)最新版?/span> 4.51,有带“I间查询”模块。各大搜索引擎都没有扑ֈ像样例子Q于是想C(jin)lucene svn?/span> trunk目录试用例中找C(jin)试例子Q开始了(jin)一D?/span>lucene之旅?/span>
写数据,创徏IndexWriter,通过它的构造函数需要一个烦(ch)引目录(DiectoryQ和索引写入配置(InderWriterConfigQ?/span>,直接上代码:(x)
//讄写入目录(好几U呵?/span>)
Directory d=FSDirectory.open(new File("D:/luceneTest"));
//讄分词 StandardAnalyzerQ会(x)把句子中的字单个分词Q?/span>
Analyzer analyzer= new StandardAnalyzer(Version.LUCENE_45);
//讄索引写入配置
IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_45,analyzer);
//讄创徏模式
//config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
IndexWriter indexwriter= new IndexWriter(d,config);
上面四行代码创建好?/span>indexwriterQ?/span>下面把数据填入就好了(jin)Q写入有多种方式如下图:(x)
?/span> addDocment 举例代码如下Q?/span>
Document doc=new Document();
doc.add(new StringField("id", "1", Store.YES));
doc.add(new StringField("name", "brockhong", Store.YES));
doc.add(new TextField("content", "lucene 文档W一ơ写看着l分?/span>", Store.YES));
//写入数据
indexwriter.addDocument(doc);
//提交
indexwriter.commit();
?/span> Luke 工具查看Text列,q是标准分词惹的哦Q写入成功?/span>
L据查询,创徏 IndexSearcher 构造函数设|?/span>indexReader Q输入查询条Ӟ上面content字段数据讄?jin)分词,所以必通过查询解析c?/span>QueryParser讑֮分词字段、版本、分词模式,q过parseҎ(gu)得到查询条g。代码如下:(x)
//L?/span>
//创徏 indexReader q个已过?/span> IndexReader.open(d)Q里面的代码一样可能ؓ(f)?jin)兼容老版?/span>
IndexReader indexReader = DirectoryReader.open(d);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//查询 讄分词字段
QueryParser queryParser = new QueryParser(Version.LUCENE_45, "content",
new StandardAnalyzer(Version.LUCENE_45));
//or 关系 “l?#8221;?#8220;?#8221;
queryParser.setDefaultOperator(QueryParser.OR_OPERATOR);
Query query = queryParser.parse("l分");
TopDocs results = indexSearcher.search(query, 100);
int numTotalHits = results.totalHits;
System.out.println("?/span> " + numTotalHits + " 完全匚w的文?/span>");
ScoreDoc[] hits = results.scoreDocs;
for (int i = 0; i < hits.length; i++) {
Document document = indexSearcher.doc(hits[i].doc);
System.out.println("content:" + document.get("content"));
}