- 浏览: 95568 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
fengweiyou:
只取当前年月日 TRUNC(SYSDATE) 就可以了
oracle函数只取年月日 -
spp_1987:
我在页面上 显示出来的 怎么是乱码啊。 能解决下吗
是什 ...
struts+jquery -
spp_1987:
//JSONObject json = JSONObject. ...
struts+jquery -
spp_1987:
不知道为什么 有错啊。 我用的是DispatchAction啊 ...
struts+jquery -
hiteny:
还是css用着方便@ 谢谢啦
css控制字符串显示长度
研究SegmentInfo类的实现。
虽然在阅读代码的时候,是一件很枯燥的事情,尤其是当代码非常地长,这使得我们感觉这是一种压力,但是如果把代码当成是一种乐趣的时候,你会发现代码是那样的富有感情色彩。呵呵。
SegmentInfo类在Lucene 2.0.0版本的时候,定义非常简单,就定义了一个构造函数,如下所示:
但是,到了2.2.0版本的时候,SegmentInfo类的定义就相当复杂了。
因为2.2.0版本是在之前的版本的基础上进行开发的,所以涉及到一些概念,尤其是文件格式,提前了解一下这些概念对于理解SegmentInfo类有很大帮助。
*************************************************************************************
Normalization Factors(标准化因子):可以参考http://lucene.apache.org/java/2_2_0/fileformats.html#Normalization%20Factors
【在2.1之前的版本,存在下面的一些格式的文件】
在每个Document逻辑文件中,对于一个被索引的Field,都对应着一个norm文件,该norm文件的一个字节与Document有非常密切的关系。
这个.f[0-9]*文件,是为每个Document设置的,当Document中的一个Field被命中的时候,.f[0-9]*文件包含的就是:一个字节编码值乘以排序分值。
一个单独的norm文件的创建,仅仅是在一个复合segments文件被创建的时候才存在。即:一个单独的norm文件的存在是依赖于复合segments的,如果复合segments文件不存在,就不会生成一个单独的norm文件。
【在2.1版本及其之后的版本,存在下面的一些格式的文件】
只使用一个.nrm文件,该文件包含了所有的标准化因子。所有的.nrm文件都包含NormsHeader和<Norms> NumFieldsWithNorms 这两部分。
其中:
NormsHeader包含4个字节,前三个字节为“N”、“R”、“M”,最后一个字节指定了FORMAT版本号,当前因为是2.2.0版本,版本号为-1,可以在SegmentInfos类的定义开始部分看到:
<Norms>对应这一个<Byte>,而NumFieldsWithNorms 对应于一个Segments的大小,即SegSize。
一个.nrm文件的每个字节都编码成一个浮点值,该字节的前3bits(即0-2)表示尾数,后5bits(即3-7)表示指数。
当一个已经存在segments文件的标准化因子值(即norm的value)被修改,同时一个单独的norm文件被创建;当Field N被修改,同时一个.sN文件被创建,这个.sN文件用来保存该Field的标准化因子值(即norm的value)。
当适当的时候,一个单独的norm文件的创建,可以是为了一个复合segments文件,也可以不是复合segments文件。
*************************************************************************************
在2.2.0版本中,SegmentInfo类实现的源代码如下所示:
通过SegmentInfo类的定义,总结一下:
1、主要针对2.1版本前后的不同形式的Segments进行处理,尤其是复合segments文件;
2、对每个Field的norm文件进行处理:设置该norm文件的gen;
3、使用write()方法,将一个处理过的Segments文件写入索引目录;
4、2.1版本以后,统一使用一个.nrm文件,该文件包含了所有的标准化因子,因为需要对2.1版本以前的版本进行支持,需要处理2.1版本之前的一些版本中,对标准化因子设置文件进行处理。
5、根据getNormFileName(int number)方法,可以总结出:
(1) 通过一个索引段文件的索引值number,可以得到它的norm文件的gen值,这个gen值其实就是这个segments的gen,即形如segments_N形式,N=gen。
(2) 2.1版本以后的,norm文件只使用一个.nrm扩展名的文件来代替以前的norm文件,则这个文件就是segments.nrm文件,并且对于同一个索引段,只有一个segments.nrm文件。
(3) 2.1版本以前的,norm文件的形式有:segments.fN、segments_N.sX两种。其中N是gen值,X是一个Field在Document中的索引值。
6、通过调用files()方法,可以获取索引目录下存在的不同扩展名的文件的一个列表,即该索引目录下的所有可能存在文件(通过文件扩展名区分),可以分出下面几组:
(1) 如果useCompoundFile=true,获取到扩展名为.cfs的复合文件;
(2) 如果useCompoundFile=false,获取到扩展名为如下的复合文件:
fnm、fdx、fdt、tii、tis、frq、prx、tvx、tvd、tvf、nrm;
(3) 如果是删除文件,获取到扩展名为.del的文件,若name="segments",delGen=6,则文件名形如segments_6.del;
(4) 如果normGen != null且normGen[i] >= YES=1,获取到扩展名为.sX的文件,若name="segments",gen=6,i=X=8,则该类文件形如segments_6.s8;
(5) 如果normGen != null且normGen[i] = NO=-1且hasSingleNormFile=false且useCompoundFile=false,获取到扩展名为.fX的文件,若 name="segments",gen=6,i=X=8,则该类文件形如segments_6.f8;
(6) 如果normGen != null且normGen[i] = CHECK_DIR=0且useCompoundFile=true,获取到扩展名为.sX的文件,若name="segments",i=X=8,则该类文件形如segments.s8;
(7) 如果normGen != null且normGen[i] = CHECK_DIR=0且hasSingleNormFile=false且useCompoundFile=false,获取到扩展名为.fX的文件,若name="segments",i=X=8,则该类文件形如segments.f8;
(8) 如果normGen == null的时候,preLockless = true或(||)(hasSingleNormFile=false且useCompoundFile=false),这时若 useCompoundFile=true,则获取到扩展名为.s的文件,若name="segments",则该类文件形如segments.s;
(9) 如果normGen == null的时候,preLockless = true或(||)(hasSingleNormFile=false且useCompoundFile=false),这时若 useCompoundFile=false,则获取到扩展名为.f的文件,若name="segments",则该类文件形如segments.f;
虽然在阅读代码的时候,是一件很枯燥的事情,尤其是当代码非常地长,这使得我们感觉这是一种压力,但是如果把代码当成是一种乐趣的时候,你会发现代码是那样的富有感情色彩。呵呵。
SegmentInfo类在Lucene 2.0.0版本的时候,定义非常简单,就定义了一个构造函数,如下所示:
package org.apache.lucene.index; import org.apache.lucene.store.Directory; final class SegmentInfo { public String name; // unique name in dir public int docCount; // number of docs in seg public Directory dir; // where segment resides public SegmentInfo(String name, int docCount, Directory dir) { this.name = name; this.docCount = docCount; this.dir = dir; } }
但是,到了2.2.0版本的时候,SegmentInfo类的定义就相当复杂了。
因为2.2.0版本是在之前的版本的基础上进行开发的,所以涉及到一些概念,尤其是文件格式,提前了解一下这些概念对于理解SegmentInfo类有很大帮助。
*************************************************************************************
Normalization Factors(标准化因子):可以参考http://lucene.apache.org/java/2_2_0/fileformats.html#Normalization%20Factors
【在2.1之前的版本,存在下面的一些格式的文件】
在每个Document逻辑文件中,对于一个被索引的Field,都对应着一个norm文件,该norm文件的一个字节与Document有非常密切的关系。
这个.f[0-9]*文件,是为每个Document设置的,当Document中的一个Field被命中的时候,.f[0-9]*文件包含的就是:一个字节编码值乘以排序分值。
一个单独的norm文件的创建,仅仅是在一个复合segments文件被创建的时候才存在。即:一个单独的norm文件的存在是依赖于复合segments的,如果复合segments文件不存在,就不会生成一个单独的norm文件。
【在2.1版本及其之后的版本,存在下面的一些格式的文件】
只使用一个.nrm文件,该文件包含了所有的标准化因子。所有的.nrm文件都包含NormsHeader和<Norms> NumFieldsWithNorms 这两部分。
其中:
NormsHeader包含4个字节,前三个字节为“N”、“R”、“M”,最后一个字节指定了FORMAT版本号,当前因为是2.2.0版本,版本号为-1,可以在SegmentInfos类的定义开始部分看到:
public static final int FORMAT = -1;
<Norms>对应这一个<Byte>,而NumFieldsWithNorms 对应于一个Segments的大小,即SegSize。
一个.nrm文件的每个字节都编码成一个浮点值,该字节的前3bits(即0-2)表示尾数,后5bits(即3-7)表示指数。
当一个已经存在segments文件的标准化因子值(即norm的value)被修改,同时一个单独的norm文件被创建;当Field N被修改,同时一个.sN文件被创建,这个.sN文件用来保存该Field的标准化因子值(即norm的value)。
当适当的时候,一个单独的norm文件的创建,可以是为了一个复合segments文件,也可以不是复合segments文件。
*************************************************************************************
在2.2.0版本中,SegmentInfo类实现的源代码如下所示:
package org.apache.lucene.index; import org.apache.lucene.store.Directory; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.IndexInput; import java.io.IOException; import java.util.List; import java.util.ArrayList; final class SegmentInfo { static final int NO = -1; // 如果不存在标准化因子.nrm文件,和.del文件 static final int YES = 1; // 如果存在标准化因子.nrm文件,和.del文件 static final int CHECK_DIR = 0; // 需要检查该索引目录,是否存在标准化因子.nrm文件,和.del文件 static final int WITHOUT_GEN = 0; // 一个索引文件的名称中,没有gen值,即:根本没有对其进行过添加(或者是追加、删除)操作 public String name; // 在索引目录中的唯一索引文件名 public int docCount; // 在索引段中Document的数量 public Directory dir; // 一个索引段文件所属于的索引目录为dir private boolean preLockless; // 为true,当一个索引段文件在无锁提交之前被写入 private long delGen; // 当前版本(generation)删除时的gen的值为delGen(即segments_delGen.del) private long[] normGen; // 每个Field对应的norm文件的gen private byte isCompoundFile; // 如果为NO,则表示不用检查;如果为YES表示检查是否存在2.1版本之前的扩展名为.cfs和.nrm的文件 private boolean hasSingleNormFile; //如果一个segments存在一个单独的norm文件。在当前版本中,false表示一个segments是由DocumentWriter生成的,true表示为最新创建的合并的索引段文件(包括复合segments文件和非复合segments文件) private List files; // 在当前索引目录中,当前索引段用到的文件在缓存中的列表 // 构造一个SegmentInfo对象(根据指定的参数:索引段名称、索引文件中Document的数量、指定的所以目录) public SegmentInfo(String name, int docCount, Directory dir) { this.name = name; this.docCount = docCount; this.dir = dir; delGen = NO; // 初始化一个SegmentInfo的时候,指定存在标准化因子.nrm文件,和.del文件 isCompoundFile = CHECK_DIR; // 检查该索引目录dir,看是否存在一些2.1版本之前的扩展名为.cfs和.nrm的文件 preLockless = true; // 为true,当一个索引段文件在无锁提交之前被写入 hasSingleNormFile = false; // 指定一个segments是由DocumentWriter生成的 } // 构造一个SegmentInfo对象 public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile) { this(name, docCount, dir); this.isCompoundFile = (byte) (isCompoundFile ? YES : NO); this.hasSingleNormFile = hasSingleNormFile; preLockless = false; // 为false,当一个索引段文件不是在无锁提交之前被写入 } /** * 根据指定的SegvmentInfo,拷贝它到我们当前的SegmentInfo实例中,其实就是重新构造一个SegmentInfo,重新构造的该SegmentInfo与指定的SegmentInfo src是相同的 */ void reset(SegmentInfo src) { files = null; name = src.name; docCount = src.docCount; dir = src.dir; preLockless = src.preLockless; delGen = src.delGen; if (src.normGen == null) { // 每个Field对应的norm文件的gen不存在(为null) normGen = null; } else { normGen = new long[src.normGen.length]; // arraycopy的声明为:public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length); System.arraycopy(src.normGen, 0, normGen, 0, src.normGen.length); } isCompoundFile = src.isCompoundFile; hasSingleNormFile = src.hasSingleNormFile; } // 构造一个SegmentInfo对象,通过构造一个索引输入流对象IndexInput SegmentInfo(Directory dir, int format, IndexInput input) throws IOException { this.dir = dir; name = input.readString(); docCount = input.readInt(); if (format <= SegmentInfos.FORMAT_LOCKLESS) { delGen = input.readLong(); if (format <= SegmentInfos.FORMAT_SINGLE_NORM_FILE) { hasSingleNormFile = (1 == input.readByte()); } else { hasSingleNormFile = false; } int numNormGen = input.readInt(); if (numNormGen == NO) { normGen = null; } else { normGen = new long[numNormGen]; for(int j=0;j<numNormGen;j++) { normGen[j] = input.readLong(); } } isCompoundFile = input.readByte(); preLockless = (isCompoundFile == CHECK_DIR); } else { delGen = CHECK_DIR; // CHECK_DIR = 0 normGen = null; isCompoundFile = CHECK_DIR; preLockless = true; // 一个索引段文件在无锁提交之前被写入过 hasSingleNormFile = false; // 一个segments是由DocumentWriter生成的 } } // 为每个Field的norm文件设置gen值 void setNumFields(int numFields) { if (normGen == null) { // 如果是2.1版本之前的segment文件,或者该segment文件没有对应的norm文件,则normGen=null normGen = new long[numFields]; if (preLockless) { // 保持normGen[k]==CHECK_DIR (==0), 之后会为这些norm文件检查文件系统,因为它们是以前版本中无锁提交的 } else { // 这是一个无锁提交写入的segment, 不存在单独的norm文件 for(int i=0;i<numFields;i++) { normGen[i] = NO; // 对每个Field,设置norm文件的gen值为NO=-1 } } } } // 是否存在.del文件 boolean hasDeletions() throws IOException { //如果delGen == NO==-1: 表示使用LOCKLESS模式,其中一些segment不存在.del文件 if (delGen == NO) { return false; } else if (delGen >= YES) { // YES的值为1,如果segment文件是无锁提交的,其中一些存在.del文件 return true; } else { return dir.fileExists(getDelFileName()); // getDelFileName()在后面定义了该方法,获取删除的该索引目录下的文件名 } } void advanceDelGen() { // delGen 0 is reserved for pre-LOCKLESS format if (delGen == NO) { delGen = YES; } else { delGen++; } files = null; } // 设置delGen的值为NO,即-1 void clearDelGen() { delGen = NO; files = null; } public Object clone () { // SegmentInfo支持克隆 SegmentInfo si = new SegmentInfo(name, docCount, dir); si.isCompoundFile = isCompoundFile; si.delGen = delGen; si.preLockless = preLockless; si.hasSingleNormFile = hasSingleNormFile; if (normGen != null) { si.normGen = (long[]) normGen.clone(); } return si; } String getDelFileName() { // 获取删除的该索引目录下的文件名 if (delGen == NO) { // 如果delGen==NO,则表示不删除 return null; } else { // 如果delGen是CHECK_DIR,,则它是以前的无锁提交格式 return IndexFileNames.fileNameFromGeneration(name, "." +IndexFileNames.DELETES_EXTENSION, delGen); // 即返回文件名为name_delGen.del,例如segments_5.del } } /** * 如果该索引段的这个Field作为separate norms文件(_<segment>_N.sX)进行存储 * fieldNumber是一个需要检查的field的索引 */ boolean hasSeparateNorms(int fieldNumber) throws IOException { if ((normGen == null && preLockless) || (normGen != null && normGen[fieldNumber] == CHECK_DIR)) { // Must fallback to directory file exists check: String fileName = name + ".s" + fieldNumber; return dir.fileExists(fileName); } else if (normGen == null || normGen[fieldNumber] == NO) { return false; } else { return true; } } /** * 返回true如果这个segments中的任何一个Field都存在一个单独的norm文件 */ boolean hasSeparateNorms() throws IOException { if (normGen == null) { // 如果normGen = null if (!preLockless) { // 不存在norm文件,返回false return false; } else { // segment使用pre-LOCKLESS模式保存,需要回退到最初的目录下,进行核查 String[] result = dir.list(); if (result == null) // 如果获取的文件列表为null throw new IOException("cannot read directory " + dir + ": list() returned null"); // 否则,如果获取的文件列表不空 String pattern; pattern = name + ".s"; // 设置文件名的匹配格式字符串,形如name.s的形式 int patternLength = pattern.length(); for(int i = 0; i < result.length; i++){ // 循环匹配 if(result[i].startsWith(pattern) && Character.isDigit(result[i].charAt(patternLength))) return true; } return false; } } else { // 如果normGen != null // 这个segment使用LOCKLESS模式保存 // 需要检查是否任何一个normGen都是 >= 1的 // (它们有一个单独的norm文件): for(int i=0;i<normGen.length;i++) { if (normGen[i] >= YES) { // YES=1 return true; } } // 查找normGen == 0的,这些情况是re // pre-LOCKLESS模式提交的,需要检查: for(int i=0;i<normGen.length;i++) { if (normGen[i] == CHECK_DIR) { if (hasSeparateNorms(i)) { return true; } } } } return false; } /** * 为每个Field的norm文件的gen,执行加1操作 * @param fieldIndex:指定的Field的norm文件需要被重写,fieldIndex即对应的norm文件的gen值 */ void advanceNormGen(int fieldIndex) { if (normGen[fieldIndex] == NO) { normGen[fieldIndex] = YES; }else { normGen[fieldIndex]++; } files = null; } /** * 获取Field的norm文件的文件名称;number是一个Field的索引值 */ String getNormFileName(int number) throws IOException { String prefix; long gen; if (normGen == null) { gen = CHECK_DIR; // CHECK_DIR==0 } else { gen = normGen[number]; // 根据Field的索引值获取它对应的norm文件的gen值,然后使用该gen值取得索引段文件的文件名 } if (hasSeparateNorms(number)) { // case 1: separate norm prefix = ".s"; return IndexFileNames.fileNameFromGeneration(name, prefix + number, gen); // 使用gen值取得索引段文件的文件名,如果name=“segments”,number=7,gen=4,则返回的文件名为segments_4.s7 } if (hasSingleNormFile) { // 如果存在一个单独的norm文件 // case 2: lockless (or nrm file exists) - single file for all norms prefix = "." + IndexFileNames.NORMS_EXTENSION; // IndexFileNames.NORMS_EXTENSION=nrm return IndexFileNames.fileNameFromGeneration(name, prefix, WITHOUT_GEN); // 如果name=“segments”,则返回的文件名为segments.nrm } // case 3: norm file for each field prefix = ".f"; return IndexFileNames.fileNameFromGeneration(name, prefix + number, WITHOUT_GEN); // 如果name=“segments”,number=7,则返回的文件名为segments.f7 } /** *指定,是否segment文件作为复合文件存储() */ void setUseCompoundFile(boolean isCompoundFile) { if (isCompoundFile) { this.isCompoundFile = YES; } else { this.isCompoundFile = NO; } files = null; } /** * 如果索引文件被作为复合文件存储,则返回true */ boolean getUseCompoundFile() throws IOException { if (isCompoundFile == NO) { return false; } else if (isCompoundFile == YES) { return true; } else { return dir.fileExists(name + "." + IndexFileNames.COMPOUND_FILE_EXTENSION); } } /** *保存segment的信息,其实就是输出(写入)到磁盘中的索引目录中 */ void write(IndexOutput output) throws IOException { output.writeString(name); output.writeInt(docCount); output.writeLong(delGen); output.writeByte((byte) (hasSingleNormFile ? 1:0)); if (normGen == null) { output.writeInt(NO); } else { output.writeInt(normGen.length); for(int j = 0; j < normGen.length; j++) { output.writeLong(normGen[j]); } } output.writeByte(isCompoundFile); } /* * 返回所有的被当前SegmentInfo引用的所有的文件的列表,由于是在本地缓存中,你不应该设法去修改他们 */ public List files() throws IOException { if (files != null) { return files; } files = new ArrayList(); boolean useCompoundFile = getUseCompoundFile(); if (useCompoundFile) { files.add(name + "." + IndexFileNames.COMPOUND_FILE_EXTENSION); // IndexFileNames.COMPOUND_FILE_EXTENSION=csf } else { /* INDEX_EXTENSIONS_IN_COMPOUND_FILE定义了如下所示的复合文件扩展名: static final String[] INDEX_EXTENSIONS_IN_COMPOUND_FILE = new String[] { "fnm", "fdx", "fdt", "tii", "tis", "frq", "prx", "tvx", "tvd", "tvf", "nrm" }; */ for (int i = 0; i < IndexFileNames.INDEX_EXTENSIONS_IN_COMPOUND_FILE.length; i++) { String ext = IndexFileNames.INDEX_EXTENSIONS_IN_COMPOUND_FILE[i]; String fileName = name + "." + ext; if (dir.fileExists(fileName)) { files.add(fileName); } } } String delFileName = IndexFileNames.fileNameFromGeneration(name, "." + IndexFileNames.DELETES_EXTENSION, delGen); // IndexFileNames.DELETES_EXTENSION=del;如果name=“segments”,delGen=6,则返回的文件名为segments_6.del if (delFileName != null && (delGen >= YES || dir.fileExists(delFileName))) { files.add(delFileName); } // Careful logic for norms files if (normGen != null) { for(int i=0;i<normGen.length;i++) { long gen = normGen[i]; if (gen >= YES) { // Definitely a separate norm file, with generation: files.add(IndexFileNames.fileNameFromGeneration(name, "." + IndexFileNames.SEPARATE_NORMS_EXTENSION + i, gen)); // IndexFileNames.SEPARATE_NORMS_EXTENSION=s;如果name=“segments”,gen=6,i=8,则返回的文件名为segments_6.s8 } else if (NO == gen) { // No separate norms but maybe plain norms // in the non compound file case: if (!hasSingleNormFile && !useCompoundFile) { String fileName = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION + i; // IndexFileNames.PLAIN_NORMS_EXTENSION=f;如果name=“segments”,gen=6,i=8,则返回的文件名为segments_6.f8 if (dir.fileExists(fileName)) { files.add(fileName); } } } else if (CHECK_DIR == gen) { // 2.1版本之前:我们需要验证这些文件的存在性 String fileName = null; if (useCompoundFile) { fileName = name + "." + IndexFileNames.SEPARATE_NORMS_EXTENSION + i; // 若name="segments",i=X=8,则该类文件形如segments.s8 } else if (!hasSingleNormFile) { fileName = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION + i; // 若name="segments",i=X=8,则该类文件形如segments.f8 } if (fileName != null && dir.fileExists(fileName)) { files.add(fileName); } } } } else if (preLockless || (!hasSingleNormFile && !useCompoundFile)) { // 2.1版本之前的: 需要为我们当前的索引段扫描索引目录找到所有的匹配的_X.sN或_X.fN的文件 String prefix; if (useCompoundFile) prefix = name + "." + IndexFileNames.SEPARATE_NORMS_EXTENSION; // 若name="segments",则该类文件形如segments.s else prefix = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION; // 若name="segments",则该类文件形如segments.f int prefixLength = prefix.length(); String[] allFiles = dir.list(); if (allFiles == null) throw new IOException("cannot read directory " + dir + ": list() returned null"); for(int i=0;i<allFiles.length;i++) { String fileName = allFiles[i]; if (fileName.length() > prefixLength && Character.isDigit(fileName.charAt(prefixLength)) && fileName.startsWith(prefix)) { files.add(fileName); } } } return files; } }
通过SegmentInfo类的定义,总结一下:
1、主要针对2.1版本前后的不同形式的Segments进行处理,尤其是复合segments文件;
2、对每个Field的norm文件进行处理:设置该norm文件的gen;
3、使用write()方法,将一个处理过的Segments文件写入索引目录;
4、2.1版本以后,统一使用一个.nrm文件,该文件包含了所有的标准化因子,因为需要对2.1版本以前的版本进行支持,需要处理2.1版本之前的一些版本中,对标准化因子设置文件进行处理。
5、根据getNormFileName(int number)方法,可以总结出:
(1) 通过一个索引段文件的索引值number,可以得到它的norm文件的gen值,这个gen值其实就是这个segments的gen,即形如segments_N形式,N=gen。
(2) 2.1版本以后的,norm文件只使用一个.nrm扩展名的文件来代替以前的norm文件,则这个文件就是segments.nrm文件,并且对于同一个索引段,只有一个segments.nrm文件。
(3) 2.1版本以前的,norm文件的形式有:segments.fN、segments_N.sX两种。其中N是gen值,X是一个Field在Document中的索引值。
6、通过调用files()方法,可以获取索引目录下存在的不同扩展名的文件的一个列表,即该索引目录下的所有可能存在文件(通过文件扩展名区分),可以分出下面几组:
(1) 如果useCompoundFile=true,获取到扩展名为.cfs的复合文件;
(2) 如果useCompoundFile=false,获取到扩展名为如下的复合文件:
fnm、fdx、fdt、tii、tis、frq、prx、tvx、tvd、tvf、nrm;
(3) 如果是删除文件,获取到扩展名为.del的文件,若name="segments",delGen=6,则文件名形如segments_6.del;
(4) 如果normGen != null且normGen[i] >= YES=1,获取到扩展名为.sX的文件,若name="segments",gen=6,i=X=8,则该类文件形如segments_6.s8;
(5) 如果normGen != null且normGen[i] = NO=-1且hasSingleNormFile=false且useCompoundFile=false,获取到扩展名为.fX的文件,若 name="segments",gen=6,i=X=8,则该类文件形如segments_6.f8;
(6) 如果normGen != null且normGen[i] = CHECK_DIR=0且useCompoundFile=true,获取到扩展名为.sX的文件,若name="segments",i=X=8,则该类文件形如segments.s8;
(7) 如果normGen != null且normGen[i] = CHECK_DIR=0且hasSingleNormFile=false且useCompoundFile=false,获取到扩展名为.fX的文件,若name="segments",i=X=8,则该类文件形如segments.f8;
(8) 如果normGen == null的时候,preLockless = true或(||)(hasSingleNormFile=false且useCompoundFile=false),这时若 useCompoundFile=true,则获取到扩展名为.s的文件,若name="segments",则该类文件形如segments.s;
(9) 如果normGen == null的时候,preLockless = true或(||)(hasSingleNormFile=false且useCompoundFile=false),这时若 useCompoundFile=false,则获取到扩展名为.f的文件,若name="segments",则该类文件形如segments.f;
发表评论
-
Lucene学习(22)
2009-10-30 11:14 876关于FieldInfos类和FieldInfo类。 Fi ... -
Lucene学习(21)
2009-10-30 11:12 841回到IndexWriter索引器类中来,学习该类添加Docum ... -
Lucene学习(20)
2009-10-30 11:06 1008关于Field类和Document类。 ... -
Lucene学习(18)
2009-10-30 10:47 1873关于SegmentInfos类的具体 ... -
Lucene学习(17)
2009-10-30 10:40 843根据16中对IndexFileDeleter ... -
Lucene学习(16)
2009-10-30 10:33 1066在接触到索引删除的策略IndexDeletionPolicy ... -
Lucene学习(15)
2009-10-30 10:28 871关于索引删除的策略IndexDeletionPolicy 。 ... -
Lucene学习(14)
2009-10-30 10:23 754RAMDirectory类是与内存目录相关的,它和FSDire ... -
Lucene学习(13)
2009-10-30 10:21 1349Directory抽象类比较常用的具体实现子类应该是FSDir ... -
Lucene学习(12)
2009-10-30 10:17 689接着昨天学习的Lucene-2.3.1 源代码阅读学习(11) ... -
Lucene学习(11)
2009-10-30 10:06 1100对数据源进行分析,是为建立索引服务的;为指定的文件建立索引,是 ... -
Lucene学习(10)
2009-10-30 10:02 837Lucene的CJKAnalyzer分析器。 CJKAnal ... -
Lucene学习(9)
2009-10-30 09:34 914Lucene的StandardAnalyzer分析器。 ... -
Lucene学习(8)
2009-10-30 09:27 812Lucene分析器的实现。 Lucene(分词)过滤器Tok ... -
Lucene学习(7)
2009-10-30 09:22 754CharTokenizer是一个抽象类 ... -
Lucene学习(6)
2009-10-29 16:16 859Lucene分析器的实现。 Lucene分词器Tokeniz ... -
Lucene学习(5)
2009-10-29 16:13 893研究Lucene分析器的实现。 Analyzer抽象类 ... -
Lucene学习(4)
2009-10-29 16:09 879建立索引,通过已经生成的索引文件,实现通过关键字检索。 ... -
Lucene学习(3)
2009-10-29 16:06 843org.apache.lucene.demo.IndexFil ... -
Lucene学习(2)
2009-10-29 15:59 808IndexWriter是一个非常重要的工具。建立索引必须从它开 ...
相关推荐
1> lucene学习笔记 2> 全文检索的实现机制 【1】lucene学习笔记的目录如下 1. 概述 3 2. lucene 的包结构 3 3. 索引文件格式 3 4. lucene中主要的类 4 4.1. Document文档类 4 4.1.1. 常用方法 4 4.1.2. 示例 4 4.2...
在构建大型文档搜索系统时,Lucene是一个强大的搜索引擎库,其功能强大且灵活性高。本课程专注于Lucene 4.x版本,旨在通过一...通过本课程的学习,学员将能够将这些知识应用于实际项目,提升搜索系统的性能和用户体验。
了解并掌握常用的外部API和框架,如Log4J(日志)、Quartz(调度)、JGroups(网络组通信)、JCache(分布式缓存)、Lucene(全文检索)等。 ### 19. 跨平台与本地接口 学习跨平台开发技巧,掌握JNI(Java Native ...
熟悉日志框架(如Log4J)、任务调度(如Quartz)、分布式缓存(如JCache)、全文搜索(如Lucene)等常用框架和API。 #### 21. 本地接口与连接器架构 学习Java Native Interface(JNI)和Java Connector ...
#### 目标19:了解面向切面编程(AOP) - **技术框架**:AspectJ、AspectWerkz等。 - **应用场景**:实现横切关注点的模块化处理。 #### 目标20:熟悉日志记录与调度框架 - **框架选择**:Log4J、Quartz等。 - **...
- **Lucene**:学习全文检索技术的基础知识。 ### 21. 本地接口与连接器 - **JNI、JCA**:掌握Java Native Interface、Java Connector Architecture等技术,实现Java与其他语言或平台的交互。 通过以上知识点的...
#### 19. **依赖注入(DI/IoC)** - Spring、PicoContainer、Avalon等框架支持自动装配对象依赖,提高代码的解耦和可测试性。 #### 20. **J2EE服务** - JNDI、JMS、JTA/JTS、JMX等服务提供命名目录访问、消息传递、...
11. **中文分词**:在Lucene和Lietu等工具中,中文分词是文本预处理的关键步骤,正向最大匹配是常见的分词算法。 12. **查找词典算法**:Trie树是构建词典和进行快速查找的高效数据结构,包括数字搜索树和Tire树,...
Elasticsearch(简称ES)是一种开源的、基于Lucene的全文搜索引擎,它提供了一个分布式、多用户环境下的搜索和分析引擎服务。ES以其高效、可扩展、实时的搜索能力在大数据处理领域备受青睐,广泛应用于日志分析、...
##### 19. ActiveMQ - **简介**:Apache出品的消息中间件。 - **链接**:[http://activemq.apache.org/](http://activemq.apache.org/) - **核心特性**: - 消息队列 - 主题发布 - 集群支持 ##### 20. JStorm - ...
Elasticsearch 是一个基于 Lucene 的开源全文搜索引擎,以其分布式、可扩展性、实时搜索以及强大的数据分析能力而受到广泛欢迎。它不仅支持文本搜索,还可以处理结构化和非结构化数据,适用于日志分析、监控、信息...
│ 19-tomcat中JVM参数优化.avi │ ├─补充2:Redis3.0新特性、主从复制、集群视频教程 │ │ 打开必读.txt │ │ │ ├─相关资料 │ │ redis-3.0.1.tar.gz │ │ redis-3.0.2.tar.gz │ │ redis-3.2.1.gem │...
总的来说,这门“19年全新录制Elasticsearc7.X搜索引擎项目实战Java架构全套视频教程”涵盖了Elasticsearch的全面知识,从基础概念到高级用法,从单一节点到分布式集群,从数据导入到可视化展现,再到与各种技术的...
Elasticsearch是一款广泛使用的开源搜索引擎,基于Lucene构建,以其近实时的搜索能力、水平可扩展性以及丰富的文档处理能力著称。Elasticsearch 2.x系列是这一产品的中早期版本,它提供了一系列的API以供开发者使用...
19. **案例分析与实战**:通过具体案例展示如何解决实际开发中的问题,提升读者的实战能力。 通过这部分的学习,开发者不仅可以掌握Hibernate的基本用法,还能了解到如何在复杂项目中有效运用Hibernate,提升开发...
Elasticsearch是一个基于Lucene的分布式、RESTful搜索和分析引擎,具备实时、高可用和弹性伸缩的特性。它的核心功能包括全文搜索、结构化搜索、聚合分析以及丰富的API支持。 二、Java API入门 1. 添加依赖 在你的...
32. **Apache Lucene**:搜索引擎库,包含文本分析组件,适用于信息检索和NLP应用。 33. **GATE (General Architecture for Text Engineering)**:综合的NLP框架,支持多种任务的开发和评估。 34. **Apache Tika**...
- 本书分为两大部分,其中第一部分名为“Meet Solr”,从第19页开始。 - 第一章“Introduction to Solr”(Solr简介)从第20页开始,包括以下几个小节: - **为什么需要搜索引擎?**(Why do I need a search ...