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添加一个单独的StoredField实例。
理解了这些,你就知道什么时候该用什么类型的Field了。
Java.util.Date该用什么field呢?这也是被问的频率比较高的一个问题,Lucene并没有提供DateField,请使用LongField代替,把Date转成毫秒数就OK了。有关Field今天就说这么多,后续我想到了再补充。
如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,
或者加裙
欢迎加入一起学习交流。