Lucene Field域的详解(二)

来源:互联网 发布:线条随鼠标特效源码 编辑:程序博客网 时间:2024/06/02 16:49

一、介绍

Field即Lucene索引文档里的域,一个文档Document可以包含多个Field域,你可以类比数据库表里可以有多个字段来理解,虽然两者不能等同,但有助于你理解每个Field包含3部分信息:域的名称,域的类型,域的值。域的值可以是String,Java.io.Reader,TokenStream,可以是byte[]字节数组,可以是数字等等,而域的类型则是有IndexableFieldType类表示的,域的名称就没什么好说的了。
为了方便我们创建Field,Lucene为我们提供了各种Field子类,如IntField, LongField, FloatField, DoubleField, BinaryDocValuesField, NumericDocValuesField, SortedDocValuesField, StringField, TextField, StoredField. 初学者看到这么多Field,估计就蒙了,什么时候该用什么Field呢。要弄清楚这些,你首先要弄清楚Field类里面的内部类里的Field.Index和Field.Store的相关静态变量的含义。
@Deprecated    public static enum Index {        /** Do not index the field value. This field can thus not be searched,      * but one can still access its contents provided it is      * {@link Field.Store stored}. */      NO {        @Override        public boolean isIndexed()  { return false; }        @Override        public boolean isAnalyzed() { return false; }        @Override        public boolean omitNorms()  { return true;  }         },        /** Index the tokens produced by running the field's      * value through an Analyzer.  This is useful for      * common text. */      ANALYZED {        @Override        public boolean isIndexed()  { return true;  }        @Override        public boolean isAnalyzed() { return true;  }        @Override        public boolean omitNorms()  { return false; }      },  
isIndexed:表示是否创建索引。
isAnalyzed:表示是否进行分词处理。
omitNorms:表示是否忽略域的标准化,这个概念是很多人很迷惑的。其实这个选项有关域的权重计算的,如果你忽略了域的标准化操作,那么在创建索引的时候就不会在域里面多开辟一个字节的空间来存储起加权编码值,因为它会多开辟一个字节的空间,所以会稍微增加了内存占用,如果你的Field都不需要额外的设置权重(注:field.setBoot(1.2)通过这样来设置域的权重值),那么你就可以设置忽略域的标准化操作,即可以减小内存占用,但它也会潜在的影响域的评分。
public static enum Store {        /** Store the original field value in the index. This is useful for short texts      * like a document's title which should be displayed with the results. The      * value is stored in its original form, i.e. no analyzer is used before it is      * stored.      */      YES,        /** Do not store the field's value in the index. */      NO    }  
Store有两个枚举值YES和NO,上面有解释说明,大概意思就是Store.YES表示会在索引中存储域的原始值,这对于比较短的文本是很有用的比如title,被存储后它才能在查询后返回的结果中显示出来。Store.NO则反之。说的再通俗点,就是把域的原始值复制一份IO写入到硬盘上的索引文件里,方便你查询的时候能再次还原显示原始的域的值。比如新闻标题你可能希望能在查询结果里显示出来,但一般新闻内容因为文本太大且也不会需要显示原始值,像这样的域就不适合存储到索引中。

再一个就是对于NumericDocValuesField这种DocValues域是干嘛的,有部分人估计也会晕,其实不必觉得晕,看看源码以及里面的注释你就懂了。
/**  * <p>  * Field that stores a per-document <code>long</code> value for scoring,   * sorting or value retrieval. Here's an example usage:  *   * <pre class="prettyprint">  *   document.add(new NumericDocValuesField(name, 22L));  * </pre>  *   * <p>  * If you also need to store the value, you should add a  * separate {@link StoredField} instance.  * */    public class NumericDocValuesField extends Field  
上面的注释的意思是这个Field作用就是用于为每个Document存储一个这样的Field,这个Field会存储一个long值,可以利用它来实现排序和打分。如果你需要去存储这个值,你应该再add添加一个单独的StoreField实例。

理解了这些,你就知道什么时候该用什么类型的Field了。Java.util.Date该用什么field呢?这也是被问的频率比较高的一个问题,Lucene并没有提供DateField,请使用LongField代替,把Date转成毫秒数就OK了。

二、总结

2.1 Field域的属性
(1). 是否分词: 分词的作用是为了索引。
需要分词--->文件名称, 文件内容。
不需要分词--->不需要索引的域不需要分词,还有就是分词后无意义的域不需要分词, 比如: id, 身份证号。
(2). 是否索引: 索引的的目的是为了搜索。需要搜索的域就一定要创建索引,只有创建了索引才能被搜索出来,不需要         搜索的域可以不创建索引。
      需要索引--->文件名称, 文件内容, id, 身份证号等。
      不需要索引--->比如图片地址不需要创建索引, e:\\xxx.jpg, 因为根据图片地址搜索无意义。
(3). 是否存储: 存储的目的是为了显示。是否存储看个人需要,存储就是将内容放入Document文档对象中保存出来,会         额外占用磁盘空间, 如果搜索的时候需要马上显示出来可以放入document中也就是要存储,这样查询显示速度快,         如果不是马上立刻需要显示出来,则不需要存储,因为额外占用磁盘空间不划算。是否存储的标准:是否要将内容展       示给用户。
2.2 域的各种类型


0 0