【Lucene学习】document包Document/Field

     -->step1: IndexWriter

Document

    -->分词、search  ...

Field

------------------Document--------------------

Document

  文档是一些部分(域)的集合,文档可以是网页、word、E-mail、磁盘文件等,总之有个特点是可以从中取出数据。并且这些文档都是由若干部分组成的,这些“部分”我们称之为域,域代表了文档或者和文档相关的一些元数据,比如网页里的正文、作者、标题、时间等,再比如对于磁盘文件域可以是文件内容、文件名、文件路径、修改时间等等。
  对于Lucene而言,为了不关心数据是来自网页还是来自word,它做了层抽象,将获取的这些文档获统一抽象成document类,而将文档中的不同信息抽象成Field类。
  建索引时,就是针对一个个Document对象来处理,添加进索引里。

public final class Document implements java.io.Serializable

Document类具备这些功能:增加及删除域、获取域对象或域值、设置及获取boost。
注:1.在一个document对象里多个域可以同名。
  2.获取的域值可以是String、byte[]。

【源码分析】

1.Document类实现了序列化java.io.Serializable接口

2.Document类里提供了一个ArrayList,用来存放Field对象。一个Document对象不会有多线程读写field。

3.向document对象里添加Fieldable型Field对象,其实是add到list中,方法如下:

public final void add(Fieldable field) {
fields.add(field);
}

其中fields是List<Fieldable> fields = new ArrayList<Fieldable>();

加进来的field是可以同名的,这样的话,同名的那些field的值在search的时候会被append起来。

removeField(String name) 用来从document对象里将某个field删除掉,本质就是通过迭代器从存放Fieldable的list里删除。

public final void removeField(String name) {
Iterator<Fieldable> it = fields.iterator();
while (it.hasNext()) {
Fieldable field = it.next();
if (field.name().equals(name)) {
it.remove();
return;
}
}
}

注意:API中对remove和add方法有这样的说明:

the removeField(s) methods like the add method only make sense prior to adding a document to an index.

如果想要改变一个已经存在的索引的内容的话,对该document对象add(Fieldable)和removeField(s)(String name)是不起作用的,如果想要达到这个目的的话,只能先将特定的document对象从index里删除,然后添加新的document对象。

Q:如果从已有index中获取document对象,然后操作add或者remove,那么索引会发生变化么?操作后通过提交更新能起作用么?

Q:boost什么作用?

------------------Field--------------------

public final class Field

extends AbstractField

implements Fieldable, Serializable

Fieldable继承图

【Fieldable】

public interface Fieldable extends Serializable

 

AbstractField】

public void setOmitTermFreqAndPositions(boolean omitTermFreqAndPositions) { this.omitTermFreqAndPositions=omitTermFreqAndPositions; }

omit 忽略 term freq, positions and payloads from postings for this field.

  在lucene建立起倒排索引后,为了实施Vector Space Model,会保存必要的信息,比如该model需要计算文档中出现的term数(term freq)以及positions(这些信息在词组搜索时会用到),但是有时候这些域只是用在布尔搜索中,它们不为相关评分做贡献,比如该域被用作过滤(权限过滤或者日期过滤),在这些布尔查询中,是不需要前面提到的额外信息的,为了节省磁盘上存储空间及加速搜索和过滤过程,可以通过Field.setOmitTermFreqAndPositions(true) 来让lucene跳过对该项的出现频率和出现位置的索引。

【Field】

构造field对象时field的值可以是String、Reader、org.apache.lucene.analysis.TokenStream、byte[]类型。

构造:

域值是Reader——isStored=false、isIndexed=true、isTokenized=true

 

 

Q:TokenStream是什么类?

 

当创建好一个域时,可以指定多个域选项来控制Lucene在将文档添加进索引后针对该域的行为。

【域选项】

域索引选项(Field.Index.*)控制该域是否被索引以及怎样索引。如果需要搜索某个域,则必须首先对该域索引。

 

public static enum Index {
NO {
@Override
public boolean isIndexed() { return false; }
@Override
public boolean isAnalyzed() { return false; }
@Override
public boolean omitNorms() { return true; }
},
ANALYZED {
@Override
public boolean isIndexed() { return true; }
@Override
public boolean isAnalyzed() { return true; }
@Override
public boolean omitNorms() { return false; }
},
NOT_ANALYZED {
@Override
public boolean isIndexed() { return true; }
@Override
public boolean isAnalyzed() { return false; }
@Override
public boolean omitNorms() { return false; }
},
//....其他域选项值省略.....
}


 

** Index.NO ——对应的域不会被搜索。但是如果该域的存储选项设置为Store.stored,那么在结果中是可以看到该域的。

** Index.ANALYZED ——该选项适用于普通文本域(正文、标题、摘要等)

field values ==>by Analyzer ==>a stream of separate tokens

这些tokens是searchable的。searchable是指当用户输入keywords,这些keywords经过Analyzer后会与上述token匹配。

** Index.NOT_ANALYZED——与Index.ANALYZED相比,对域进行索引,但不会对String域值利用Analyzer进行分析,即将该域值作为单一token

并使之能够被搜索。该选项适用于那些不被分解的域值,比如URL、文件路径、日期、人名、号码、标识ID等,尤其适用于“精确匹配”搜索。

 

Q:isIndexed和isAnalyzed有何区别?isIndexed决定该域是否被索引,也就决定了该域是否能够被搜索。isAnalyzed决定了是否对该域值使用Analyzer,如果使用,则域值会被分解为若干个token,否则作为单一token。

** Index.ANALYZED_NO_NORMS

Index.ANALYZED的变体

** Index.NOT_ANALYZED_NO_NORMS

Index.NOT_ANALYZED的变体

 

 

关于

1.norms参见

2.倒排索引

3.Vector Space Model

域存储选项(Index.Store.*) 决定域的原始值是否被存储在索引中,如果存储则会随搜索结果展示。

 

public static enum Store {

YES {
@Override
public boolean isStored() { return true; }
},
NO {
@Override
public boolean isStored() { return false; }
};

public abstract boolean isStored();
}

** Store.YES 适用于那些文本比较短并且需要在搜索结果中展示的域,比如URL、标题、id。按照原始值来存储,并且存储前不会使用analyzer。

** Store.NO

域的项向量选项term vectors(Field.TermVector)

 

public static enum TermVector {
NO {
@Override
public boolean isStored() { return false; }
@Override
public boolean withPositions() { return false; }
@Override
public boolean withOffsets() { return false; }
},
YES {
@Override
public boolean isStored() { return true; }
@Override
public boolean withPositions() { return false; }
@Override
public boolean withOffsets() { return false; }
},
WITH_POSITIONS {
@Override
public boolean isStored() { return true; }
@Override
public boolean withPositions() { return true; }
@Override
public boolean withOffsets() { return false; }
},
WITH_OFFSETS {
@Override
public boolean isStored() { return true; }
@Override
public boolean withPositions() { return false; }
@Override
public boolean withOffsets() { return true; }
},
WITH_POSITIONS_OFFSETS {
@Override
public boolean isStored() { return true; }
@Override
public boolean withPositions() { return true; }
@Override
public boolean withOffsets() { return true; }
};
public static TermVector toTermVector(boolean stored, boolean withOffsets, boolean withPositions) {

// If it is not stored, nothing else matters.
if (!stored) {
return TermVector.NO;
}

if (withOffsets) {
if (withPositions) {
return Field.TermVector.WITH_POSITIONS_OFFSETS;
}
return Field.TermVector.WITH_OFFSETS;
}

if (withPositions) {
return Field.TermVector.WITH_POSITIONS;
}
return Field.TermVector.YES;
}

public abstract boolean isStored();
public abstract boolean withPositions();
public abstract boolean withOffsets();
}



 

 

转载于:https://www.cnblogs.com/corson/archive/2011/12/26/2301458.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值