- 浏览: 270638 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (195)
- EXT学习 (2)
- hibernate (3)
- drools (1)
- TDD测试驱动开发 (3)
- js (7)
- php (3)
- appfuse (2)
- css (5)
- 站长文库 (15)
- flex (6)
- lucene (43)
- 业务建模 (1)
- Pentaho Report Designer (1)
- 代码质量 (10)
- webservice (2)
- 美工 (3)
- dot net (7)
- 人生 (5)
- 方法论 (3)
- html (4)
- 需求管理 (2)
- 资源分享 (2)
- JAVA (6)
- IDE--intelij文章收集 (5)
- 爬虫学习 (1)
- air (2)
- json转换 (1)
- Linux (2)
- C C++ (1)
- mysql word export 导出 (1)
- avast windows server 2003 (3)
- Linux yum (1)
- flash as3 actionscript 错误码 参考 (1)
- actionscript (1)
- 快速开发 (2)
- ios (0)
- erLang (1)
- 手机开发 (1)
- mysql (1)
- 苹果 MacOs (1)
最新评论
-
cuidongdong1234:
有没有源码分析呀?
初步了解jackson -
ieblaze:
您好!我测试了下 ,启动不成警告: Could not get ...
Embed Tomcat 开发,调试项目 -
Feegle7:
楼主,你这个ppt太花了,估计,大家根本没心思看内容了
drools的学习总结 -
filix:
zhoche2008 写道本来写得挺好的。非要搞一些PPT动画 ...
drools的学习总结 -
zhoche2008:
这PPT真耗资源,服了
drools的学习总结
阅读了这么多代码,该综合总结一下了。
通过在文章 Lucene-2.2.0 源代码阅读学习(4) 中的那个例子,跟踪一下一个IndexWriter索引器实例化过程,及其建立索引的过程中都经过了哪些处理(主要看涉及到了哪些类来完成建立索引的强大功能)。
在文章 Lucene-2.2.0 源代码阅读学习(4) 中的主函数如下所示:
public static void main(String[] args){
MySearchEngine mySearcher = new MySearchEngine();
String indexPath = "E:\\Lucene\\myindex";
File file = new File("E:\\Lucene\\txt");
mySearcher.setIndexPath(indexPath);
mySearcher.setFile(file);
IndexWriter writer;
try {
writer = new IndexWriter(mySearcher.getIndexPath(),new CJKAnalyzer(),true);
mySearcher.createIndex(writer, mySearcher.getFile());
mySearcher.searchContent("contents","注册");
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
从红色标注的代码行看起:
初始化一个IndexWriter索引器的时候(红色标注的第一行代码),还没有向其中添加任何的Document。当执行到红色标注的第二行的时候,开始从指定的本地磁盘目录中读取数据源文件(没有经过任何处理),并且根据已经存在的IndexWriter索引器writer,向这个writer中添加Document,可以看到文章 Lucene-2.2.0 源代码阅读学习(4) 中createIndex()方法中的处理是这样的:
writer.addDocument(FileDocument.Document(file));
具体地,从本地磁盘指定目录中读取文件,调用FileDocument类的Document()方法对待处理的原始文件进行一番处理,主要是构造Field,并将构造好的Field添加到Document中,如下所示:
// 通过f的所在路径构造一个Field对象,并设定该Field对象的一些属性:
// “path”是构造的Field的名字,通过该名字可以找到该Field
// Field.Store.YES表示存储该Field;Field.Index.UN_TOKENIZED表示不对该Field进行分词,但是对其进行索引,以便检索
doc.add(new Field("path", f.getPath(), Field.Store.YES, Field.Index.UN_TOKENIZED));
// 构造一个具有最近修改修改时间信息的Field
doc.add(new Field("modified",
DateTools.timeToString(f.lastModified(), DateTools.Resolution.MINUTE),
Field.Store.YES, Field.Index.UN_TOKENIZED));
// 构造一个Field,这个Field可以从一个文件流中读取,必须保证由f所构造的文件流是打开的
doc.add(new Field("contents", new FileReader(f)));
处理完成之后,最后返回一个Document对象,这个Document对象已经含有一定的信息了。接着就把返回的一个个Document对象加入到IndexWriter writer索引器中。
自然而然,从writer.addDocument(FileDocument.Document(file));可以看到,调用的IndexWriter类的addDocumnet()方法,对加入到其中的Document进行处理。这个处理是相当复杂的,我们一步步跟踪它的处理过程,掌握它建立索引的历程。
为了直观,设置了分级序号,即在一个类中是顶级,在该类的某个方法第一次被调用的时候为一级,在此方法中调用到的其他方法都为一级的子级,以此类推。
现在,进入到IndexWriter索引器(IndeWriter writer已经存在,打开了一个流)的内部:
在IndexWriter类中:
1、addDocument()方法中
public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException {
ensureOpen();
SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
synchronized (this) {
ramSegmentInfos.addElement(newSegmentInfo);
maybeFlushRamSegments();
}
}
通过上面知道,传递进来的Document doc和Analyzer analyzer都已经存在在内存中了,可以随时使用他们。
整体概括层次(1.x)
—1.1、调用了ensureOpen()方法
看IndexWriter的addDocument()方法中,首先调用了ensureOpen()方法,该方法根据一个closed标识来保证当前实例化的IndexWriter是否处于打开状态。关于closed的标识的设置,当一个IndexWriter索引器实例化的时候,该值就已经初始化为false了,表示索引器writer已经处于打开状态。如果想要关闭writer,直接调用IndexWriter类的close()方法,可以设置closed的标识为true,表示索引器被关闭了,不能进行有关建立索引的操作了。
—1.2、调用了buildSingleDocSegment(doc, analyzer)方法
IndexWriter的addDocument()方法中,调用buildSingleDocSegment(doc, analyzer)方法,根据传递进来的doc和analyzer(它们都存在于当前的内存中),构造了一个SegmentInfo对象。具体构造过程如下所示:
SegmentInfo buildSingleDocSegment(Document doc, Analyzer analyzer)
throws CorruptIndexException, IOException {
DocumentWriter dw = new DocumentWriter(ramDirectory, analyzer, this);
dw.setInfoStream(infoStream);
String segmentName = newRamSegmentName();
dw.addDocument(segmentName, doc);
SegmentInfo si = new SegmentInfo(segmentName, 1, ramDirectory, false, false);
si.setNumFields(dw.getNumFields());
return si;
}
该buildSingleDocSegment()方法,通过使用DocumentWriter类的实例,实现对Document doc进行处理,处理的过程中使用了传递进来的Analyzer analyzer分析器。
处理完成以后,才构造的SegmentInfo对象,并且根据已经存在的DocumentWriter实例所包含的信息,设置SegmentInfo对象的内容,最后返回一个SegmentInfo si实例。
—1.3、向SegmentInfos中添加一个SegmentInfo
即:ramSegmentInfos.addElement(newSegmentInfo);
—1.4、向SegmentInfos中添加一个SegmentInfo
即:maybeFlushRamSegments();
该方法在IndexWriter类中定义用来监测当前缓冲区,及时将缓冲区中的数据flush到索引目录中。其中可能存在索引段合并的问题。实现代码如下所示:
protected final void maybeFlushRamSegments() throws CorruptIndexException, IOException {
// 如果缓冲区中有足够多的新的Document,或者足够的缓冲的删除的词条
if (ramSegmentInfos.size() >= minMergeDocs || numBufferedDeleteTerms >= maxBufferedDeleteTerms) {
flushRamSegments();
}
}
调用的 flushRamSegments()方法的定义为:
private final synchronized void flushRamSegments() throws CorruptIndexException, IOException {
flushRamSegments(true);
}
这里又调用了flushRamSegments()方法,定义如下:
protected final synchronized void flushRamSegments(boolean triggerMerge)
throws CorruptIndexException, IOException {
if (ramSegmentInfos.size() > 0 || bufferedDeleteTerms.size() > 0) {
mergeSegments(ramSegmentInfos, 0, ramSegmentInfos.size());
if (triggerMerge) maybeMergeSegments(minMergeDocs);
}
}
该方法调用的两个方法mergeSegments()和maybeMergeSegments()才是合并索引段最核心的操作,参考后文。
详细解析层次1.1.x(无)
详细解析层次1.2.x
— —1.2.1、构造DocumentWriter实例
构造一个DocumentWriter实例,需要三个参数。这里:
第一个是ramDirectory,它是IndexWriter类的一个成员,是RAMDirectory类的实例,该类的实例与内存中的目录操作有密切关系。
第二个是analyzer,一个在内存中存在的Analyzer实例。
第三个是this,即当前的这个IndexWriter writer索引器的实例。
DocumentWriter类的这个构造方法定义如下:
DocumentWriter(Directory directory, Analyzer analyzer, IndexWriter writer) {
this.directory = directory;
this.analyzer = analyzer;
this.similarity = writer.getSimilarity();
this.maxFieldLength = writer.getMaxFieldLength();
this.termIndexInterval = writer.getTermIndexInterval();
}
可见,在构造一个DocumentWriter的实例的时候,在该构造函数所具有的参数以外,还设定了DocumentWriter类的几个成员属性的值。一共额外设置了三个属性值,都是从IndexWriterwriter索引器中获取到的。其中:
Similarity是在一个IndexWriter writer实例化的时候,便设置了它的内容,它是关于标准化因子的内容的,可以从IndexWriter类中找到该成员的设置如下所示:
private Similarity similarity = Similarity.getDefault();
使用了默认的Similarity,即DefaultSimilarity类的一个实例,该DefaultSimilarity类是Similarity类的继承子类,该类与检索的关系非常密切。(后面再学习)
maxFieldLength指一个可以为多少个Field建立索引,在Lucene中指定的默认的值为10000,可以根据需要修改这个数值。可以从IndexWriter类中看到定义:
public final static int DEFAULT_MAX_FIELD_LENGTH = 10000
termIndexInterval是词条索引区间,与在内存中处理词条相关。如果该值设置的越大,则导致IndexReader使用的内存空间就越小,也就减慢了词条Term的随机存储速度。该参数决定了每次查询要求计算词条Term的数量。在Lucene中的默认值为128,仍然可以从IndexWriter类中看到定义:
public final static int DEFAULT_TERM_INDEX_INTERVAL = 128;
— —1.2.2、为已经构造好的DocumentWriter dw设置一个PrintStream流
即:dw.setInfoStream(infoStream);
一个PrintStream是一个过滤流,继承自FilterOutputStream类。它可以加入到另一个输出流中,并且很方便地把它所具有的各种信息打印出来。PrintStream流具有很好的性能。
— —1.2.3、在内存中创建一个临时的索引段的名称
即:String segmentName = newRamSegmentName();
调用了IndexWriter类的newRamSegmentName(),生成一个临时的索引段名称,该newRamSegmentName()方法比较简单:
final synchronized String newRamSegmentName() {
return "_ram_" + Integer.toString(ramSegmentInfos.counter++, Character.MAX_RADIX);
}
ramSegmentInfos是SegmentInfos类的实例,该类的counter成员是用来为将要写入到索引目录中的索引段文件命名的,应该是内部名,counter的信息后写入到索引段文件中。如果第一次调用该方法,生成的名称为_ram_1。
— —1.2.4、调用DocumentWriter类的addDocument()方法对doc进行处理
即dw.addDocument(segmentName, doc);
关于该方法的说明可以参考文章 Lucene-2.2.0 源代码阅读学习(21) 。
这里,叙述一下在addDocument()方法中都做了哪些事情:
首先,在addDocument()方法中构造了一个FieldInfos对象,将传递进来的doc加入到其中。从doc中提取关于Field的信息,将操作频繁的信息提取出来,构造一个个的FieldInfo对象。然后FieldInfos在对FieldInfo进行管理。
关于FieldInfos类和FieldInfo的说明可以参考文章 Lucene-2.2.0 源代码阅读学习(22) 。
其次,在addDocument()方法中利用FieldInfos管理FieldInfo的便利性,再次提取Field的信息,构造Posting类的实例,关于Posting类说明可以参考文章 Lucene-2.2.0 源代码阅读学习(23) 。这里面,在一个FieldInfos写入到索引文件之前,要对doc进行倒排(因为doc已经加入到FieldInfos中了),倒排的过程中对Field进行了分词处理。
再次,对doc倒排之后,形成一个Posting[]数组,接着对它进行排序(使用快速排序),之后FieldInfos才能将各个Field的名称写入索引目录中fieldInfos.write(directory, segment + ".fnm");。如果传递进来的segment值为_ram_1它写到了文件_ram_1.fnm文件中。
接着,构造一个FieldsWriter对象:new FieldsWriter(directory, segment, fieldInfos),并且将doc添加到FieldWriter对象中,即fieldsWriter.addDocument(doc),在FieldWriter的addDocument中进行了处理。
最后,处理的是:
writePostings(postings, segment);
writeNorms(segment);
writePostings()方法的实现可以参考文章 Lucene-2.2.0 源代码阅读学习(23) 。
writeNorms()方法的实现如下:
private final void writeNorms(String segment) throws IOException {
for(int n = 0; n < fieldInfos.size(); n++){
FieldInfo fi = fieldInfos.fieldInfo(n);
if(fi.isIndexed && !fi.omitNorms){
float norm = fieldBoosts[n] * similarity.lengthNorm(fi.name, fieldLengths[n]);
IndexOutput norms = directory.createOutput(segment + ".f" + n);
try {
norms.writeByte(Similarity.encodeNorm(norm));
} finally {
norms.close();
}
}
}
}
— —1.2.5、根据经过处理的信息,构造SegmentInfo对象
即:
SegmentInfo si = new SegmentInfo(segmentName, 1, ramDirectory, false, false);
si.setNumFields(dw.getNumFields());
SegmentInfo的该构造函数声明如下:
public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile)
第一个参数就是索引的文件名,第二个参数是Document的数量,第三个指定是否是复合文件,第四个参数指定是否具有单独的norm文件。
因为是在Lucene 2.2.0版本,已经不使用单独的norm文件了,一个索引段由一个文件统一管理nrom信息。
这里默认设置了Document的数量为1个,且不使用复合文件。
第二行si.setNumFields(dw.getNumFields());,为这个SegmentInfo对象设置Field的数量信息。
最后返回构造好的该SegmentInfo对象。
详细解析层次1.2.4.x
— — —1.2.4.1、关于FieldInfos的第一个write()方法
FieldInfos有两个write()方法,第二个是核心的,先把参数传进第一个方法中:
public void write(Directory d, String name) throws IOException {
IndexOutput output = d.createOutput(name);
/*
if(d instanceof RAMDirectory){
System.out.println("d is a instance of RAMDirectory! ");
}
else if(d instanceof FSDirectory){
System.out.println("d is a instance of FSDirectory! ");
}
*/
try {
write(output); // 调用核心的write()方法
} finally {
output.close();
}
}
上面注释掉的一段代码是用来检测传递进来的Dicrectory到底是FSDirectory还是RAMDirectory。经过测试,这里面传递进来的是实现类RAMDirectory的实例。
— — —1.2.4.2、关于FieldInfos的第二个核心的write()方法
看第一个write()方法中:
IndexOutput output = d.createOutput(name);
返回了一个有name构造的RAMOutputStream输内存出流对象。
接着以output作为参数,调用了FieldInfos的第二个核心的write()方法,该方法实现如下所示:
public void write(IndexOutput output) throws IOException {
output.writeVInt(size());
for (int i = 0; i < size(); i++) {
FieldInfo fi = fieldInfo(i);
byte bits = 0x0;
if (fi.isIndexed) bits |= IS_INDEXED;
if (fi.storeTermVector) bits |= STORE_TERMVECTOR;
if (fi.storePositionWithTermVector) bits |= STORE_POSITIONS_WITH_TERMVECTOR;
if (fi.storeOffsetWithTermVector) bits |= STORE_OFFSET_WITH_TERMVECTOR;
if (fi.omitNorms) bits |= OMIT_NORMS;
if (fi.storePayloads) bits |= STORE_PAYLOADS;
output.writeString(fi.name);
output.writeByte(bits);
}
}
根据对该层次的详细叙述, output.writeVInt(size());已经将FieldInfos中FieldInfo的个数的数值写入到当前的缓冲区中了。接着看FieldInfos的第二个write()方法的继续执行:
通过一个for循环,根据指定的位置索引(FieldInfo的编号),遍历每个FieldInfo,对其一些属性进行处理后写入。
byte bits = 0x0;
if (fi.isIndexed) bits |= IS_INDEXED;
if (fi.storeTermVector) bits |= STORE_TERMVECTOR;
if (fi.storePositionWithTermVector) bits |= STORE_POSITIONS_WITH_TERMVECTOR;
if (fi.storeOffsetWithTermVector) bits |= STORE_OFFSET_WITH_TERMVECTOR;
if (fi.omitNorms) bits |= OMIT_NORMS;
if (fi.storePayloads) bits |= STORE_PAYLOADS;
output.writeString(fi.name);
output.writeByte(bits);
很容易,其实就是通过一个字节来识别各个属性(比如是否索引、是否存储词条向量、是否忽略norms、是否存储Payload信息),最后将FieldInfo的name和这些经过处理的属性写入到输出流中。
详细解析层次1.2.4.1.x
— — — —1.2.4.1.1、根据传进来的name,使用RAMDirectory的createOutput()方法创建一个输出流
即:IndexOutput output = d.createOutput(name);
这时,可以看到,接下来的一些操作都转入到RAMDirectory中去了。也就是根据一个name参数,我们看一下name在进入到RAMDirectory中的过程中发生了怎样的变化。
RAMDirectory的createOutput()方法定义如下所示:
public IndexOutput createOutput(String name) {
ensureOpen();
RAMFile file = new RAMFile(this);
synchronized (this) {
RAMFile existing = (RAMFile)fileMap.get(name);
if (existing!=null) {
sizeInBytes -= existing.sizeInBytes;
existing.directory = null;
}
fileMap.put(name, file);
}
return new RAMOutputStream(file);
}
RAMDirectory拥有一个成员变量fileMap(它是一个HashMap),在调用ensureOpen()方法时,通过fileMap来判断,如果fileMap=null,则抛出异常,终止程序流程。所以当fileMap!=null的时候说明RAMDirectory是处于打开状态的。
根据已经处于打开状态的this(即RAMDirectory),以其作为参数构造一个 RAMFile file。接着,以当前打开的RAMDirectory作为同步信号量,从fileMap中获取名称为name的一个RAMFile的实例existing,如果内存中不存在名称为name的RAMFile,则要把该RAMFile添加到fileMap中,即fileMap.put(name, file);,同时直接返回以当前RAMDirectory作为参数构造的RAMFile file;如果RAMFile existing存在,则以该name构造的RAMField作为参数,添加到RAMOutputStream内存输出流中。
这里RAMDirectory的sizeInBytes成员指定了当前RAMDirectory中操作的字节数,而对于每个RAMFile都与一个RAMDirectory相关,所以,当从内存中把一个RAMFile放到内存输出流RAMOutputStream中时,当前内存中的字节数便减少了该RAMFile所具有的字节数,即 sizeInBytes -= existing.sizeInBytes;。同时,这个RAMFile进入到了RAMOutputStream中,即表示该文件已经不与RAMDirectory相关了,所以上面有existing.directory = null;。
详细解析层次1.2.4.2.x
— — — —1.2.4.2.1、关于FieldInfos的size()方法
即: output.writeVInt(size());
先看到了size()方法,他是在FieldInfos类的一个方法,定义如下所示:
public int size() {
return byNumber.size();
}
byNumber是FieldInfos类的一个成员,它是一个ArrayList列表,该列表中添加的是一个个的FieldInfo对象,而每个FieldInfo都有一个编号number,可以根据指定的编号从byNumber列表中将FieldInfo取出来,例如,如果指定位置filedNumber,取出该位置上的FieldInfo对象可以使用byNumber.get(filedNumber)。
可见,size()方法返回的是FieldInfos中含有FieldInfo对象的个数。
— — — —1.2.4.2.2、关于IndexOutput的writeVInt()方法
方法定义如下所示:
public void writeVInt(int i) throws IOException {
while ((i & ~0x7F) != 0) {
writeByte((byte)((i & 0x7f) | 0x80));
i >>>= 7;
}
writeByte((byte)i);
}
该方法中,0x7F的值为127,按位取反后~0x7F的值为-128。
当0<=i<=127时,(i & ~0x7F) =0;当128<=i<=255时,(i & ~0x7F) =128;当256<=i<=511时,(i & ~0x7F) =256;以此类推。
也就是说,判断的条件不等于0成立 ,i的取值范围是i>=128。
调用了RAMOutputStream类的writeBytes()方法,写入的字节值为(i & 0x7f) | 0x80,因为,(i & ~0x7F)的值为0,128,256,384,512……,再与0x80(即128)做按位或运算,也就是当(i & 0x7f) 的值为0时,写入的字节是128,从而(i & 0x7f) | 0x80为写入的值:128,256,384,512……,没有0了。
详细解析层次1.2.4.2.2.x
— — — — —1.2.4.2.2.1、关于RAMOutputStream类的writeBytes()方法
output是RAMOutputStream类的一个实例,所以在操作字节时使用了RAMOutputStream类的writeBytes()方法,定义如下:
public void writeByte(byte b) throws IOException {
if (bufferPosition == bufferLength) {
currentBufferIndex++;
switchCurrentBuffer();
}
currentBuffer[bufferPosition++] = b;
}
如果bufferPosition == bufferLength,即缓冲区满,需要动态增加当前buffer的容量,索引位置增加1,当前索引位置在buffer的最后位置,然后调用switchCurrentBuffer()方法,实现字节缓冲区的动态分配:
private final void switchCurrentBuffer() throws IOException {
if (currentBufferIndex == file.buffers.size()) {
currentBuffer = file.addBuffer(BUFFER_SIZE);
} else {
currentBuffer = (byte[]) file.buffers.get(currentBufferIndex);
}
bufferPosition = 0;
bufferStart = BUFFER_SIZE * currentBufferIndex;
bufferLength = currentBuffer.length;
}
否则。缓冲区未满,可以写入。
把将待写入的经过处理的FieldInfo的个数数值,以128个字节为最小单位,写入到当前的缓冲区中,不够128个字节,填充到128个字节,不能截断数据。
发表评论
-
Lucene-2.2.0 源代码阅读学习(40)
2009-06-04 14:37 1202关于Lucene检索结果的排序问题。 已经知道,Luce ... -
Lucene-2.2.0 源代码阅读学习(39)
2009-06-04 14:35 892关于Lucene得分的计算。 在IndexSearche ... -
Lucene-2.2.0 源代码阅读学习(38)
2009-06-04 14:34 1491关于QueryParser。 QueryPars ... -
Lucene-2.2.0 源代码阅读学习(37)
2009-06-04 14:32 965关于MultiTermQuery查询。 ... -
Lucene-2.2.0 源代码阅读学习(36)
2009-06-04 14:23 1044关于MultiTermQuery查询。 ... -
Lucene-2.2.0 源代码阅读学习(35)
2009-06-04 14:22 754关于MultiPhraseQuery(多短语查询)。 Mul ... -
Lucene-2.2.0 源代码阅读学习(34)
2009-06-04 14:21 1112关于PhraseQuery。 PhraseQuery查询是将 ... -
Lucene-2.2.0 源代码阅读学习(33)
2009-06-04 14:20 809关于范围查询RangeQuery ... -
Lucene-2.2.0 源代码阅读学习(32)
2009-06-04 14:18 1117关于SpanQuery(跨度搜索),它是Query的子类,但是 ... -
Lucene-2.2.0 源代码阅读学习(31)
2009-06-04 14:15 1064关于前缀查询PrefixQuery(前缀查询)。 准备工作就 ... -
Lucene-2.2.0 源代码阅读学习(30)
2009-06-04 14:14 855关于Query的学习。 主要使用TermQuery和Bool ... -
Lucene-2.2.0 源代码阅读学习(29)
2009-06-04 14:12 1046关于IndexSearcher检索器。 ... -
Lucene-2.2.0 源代码阅读学习(28)
2009-06-04 14:09 932关于检索的核心IndexSearcher类。 IndexSe ... -
Lucene-2.2.0 源代码阅读学习(27)
2009-06-04 14:07 867关于Lucene的检索(IndexSearcher)的内容 ... -
Lucene-2.2.0 源代码阅读学习(26)
2009-06-04 14:06 1127如果在初始化一个IndexWr ... -
Lucene-2.2.0 源代码阅读学习(25)
2009-06-04 14:03 864复合索引文件格式(.cfs)是如何产生的?从这个问题出发,研究 ... -
Lucene-2.2.0 源代码阅读学习(23)
2009-06-04 13:55 822通过对DocumentWriter类的writePosting ... -
Lucene-2.2.0 源代码阅读学习(22)
2009-06-04 13:54 869关于FieldInfos类和FieldInfo类。 Fi ... -
Lucene-2.2.0 源代码阅读学习(21)
2009-06-04 13:53 839回到IndexWriter索引器类 ... -
Lucene-2.2.0 源代码阅读学习(20)
2009-06-04 13:52 849关于Field类和Document类。 初始化一个Index ...
相关推荐
lucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-...
标题中的"lucene-2.2.0zip"指的是Lucene的2.2.0版本,这是一个较早的版本,对于学习和理解Lucene的基础概念非常有帮助。 Lucene 2.2.0的主要特性包括: 1. **全文检索**:Lucene支持对文档内容进行全文检索,允许...
lucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jar
《Lucene-2.3.1 源代码阅读学习》 Lucene是Apache软件基金会的一个开放源码项目,它是一个高性能、全文本搜索库,为开发者提供了在Java应用程序中实现全文检索功能的基础架构。本篇文章将深入探讨Lucene 2.3.1版本...
《深入解析Lucene高亮显示源码:剖析`lucene-highlighter-2.2.0-src.zip`》 Lucene,作为一个开源全文检索库,以其高效、灵活的特点在信息检索领域广泛应用。在处理搜索结果时,为了提升用户体验,通常会采用高亮...
《深入剖析Lucene 2.2.0源代码》 Lucene是一款强大的开源全文搜索引擎库,由Apache软件基金会开发并维护。它为Java开发者提供了一种高性能、可扩展的文本检索核心工具。本文将深入探讨Lucene 2.2.0版本的源代码,...
在前面Lucene-2.2.0 源代码阅读学习(1)中,根据Lucene提供的一个Demo,详细分析研究一下索引器org.apache.lucene.index.IndexWriter类,看看它是如果定义的,掌握它建立索引的机制。 通过IndexWriter类的实现源代码...
赠送源代码:lucene-analyzers-smartcn-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-smartcn-7.7.0.pom; 包含翻译后的API文档:lucene-analyzers-smartcn-7.7.0-javadoc-API文档-中文(简体)版....
赠送源代码:lucene-core-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.7.0.pom; 包含翻译后的API文档:lucene-core-7.7.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
- 通过阅读源代码,可以理解Lucene的内部工作原理,如如何构建索引、执行查询等。 - 分析器部分的源码有助于了解文本预处理过程,包括分词、去除停用词等。 - 探究查询解析器的实现,掌握如何将自然语言转化为...
赠送源代码:lucene-analyzers-common-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-common-6.6.0.pom; 包含翻译后的API文档:lucene-analyzers-common-6.6.0-javadoc-API文档-中文(简体)版.zip;...
这是一个java开发用的.jar文件,用它和Lucene-core-2.0.0.jar可以实现搜索引擎
赠送源代码:lucene-core-7.2.1-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.2.1.pom; 包含翻译后的API文档:lucene-core-7.2.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
赠送源代码:lucene-suggest-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-suggest-6.6.0.pom; 包含翻译后的API文档:lucene-suggest-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....
赠送源代码:lucene-backward-codecs-7.3.1-sources.jar; 赠送Maven依赖信息文件:lucene-backward-codecs-7.3.1.pom; 包含翻译后的API文档:lucene-backward-codecs-7.3.1-javadoc-API文档-中文(简体)-英语-对照...
赠送源代码:lucene-core-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-core-6.6.0.pom; 包含翻译后的API文档:lucene-core-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
赠送源代码:lucene-spatial-extras-7.3.1-sources.jar; 赠送Maven依赖信息文件:lucene-spatial-extras-7.3.1.pom; 包含翻译后的API文档:lucene-spatial-extras-7.3.1-javadoc-API文档-中文(简体)-英语-对照版....
赠送源代码:lucene-memory-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-memory-6.6.0.pom; 包含翻译后的API文档:lucene-memory-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:...
赠送源代码:lucene-suggest-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-suggest-7.7.0.pom; 包含翻译后的API文档:lucene-suggest-7.7.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....
赠送源代码:lucene-analyzers-smartcn-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-smartcn-7.7.0.pom; 包含翻译后的API文档:lucene-analyzers-smartcn-7.7.0-javadoc-API文档-中文(简体)-英语...