【Lucene3.0 初窥】数据源内存组织结构—Document/Field

在检索数据的时候,我们很希望可以检索出数据源的各种信息。就比如检索磁盘文件,可以检索出文件的路径,名字, 内容,修改时间等等。再比如检索图书的书号、书名、作者、出版时间....  Lucene是如何组织这些数据源的不同属性信息呢?

 

Lucene 数据源组织结构

 

org.apache.lucene.document包中有两个很重要的类:Document 和 Field。这两个类将杂乱无章的数据形式组织成可以被Lucene使用的内存数据结构。

 

Field类的作用主要是用来表示当前数据源的各种属性。 数据源的每种属性信息都可以组织成一个Field对象。这些对象有不同的属性名,属性值,以及属性数据的存储方式和索引方式。

 

举个列子,比如我们想要检索文件的路径,修改时间和内容。我们可以创建三个Field对象分别存储这三种数据:

//文件路径Field
Field pathField=new Field("path", file.getPath(), Field.Store.YES, Field.Index.NOT_ANALYZED)
//文件修改时间Field
Field modifiedField=new Field("modified", DateTools.timeToString(file.lastModified(), DateTools.Resolution.MINUTE), Field.Store.YES, Field.Index.NOT_ANALYZED)
//文件内容Field
Field contentField=new Field("contents", new FileReader(file));

 

下面是Field构造器(Field构造器有很多种,这里只做简单说明)

/**
 * name:  名字
 * value:  需要处理的字符串
 * store:  是否需要将Field的原始value保存在索引文件中
 * index:  是否需要对Field的原始value建立索引,如果需要,那么Field值要被分词。
 */
public Field(String name, String value, Store store, Index index) 

 

Store和Index是Field中的枚举类型,用来表示这个Field的存储和索引方式。它们主要是为了告诉Lucene,哪些数据不需要存储,哪些数据不需要检索。

/** 
 *  确定该Field的原始value是否需要存储在索引中
 */
enum Store {
    //该Field的原始值要被存储在索引中
    //对短文本很有用。比如一个文档的标题,这个value以原始形式存储,在存储之前并不通过analyze分词
    YES {
          public boolean isStored() { return true; }
    },
    //该Field的原始值不需要存储在索引中
    NO {
          public boolean isStored() { return false; }
    };
    public abstract boolean isStored();
}
/**
 *   确定该Field是否需要索引
 */
enum Index{
      //该Field的值不需要索引,也就是不能提供关于这种Field值的查询
      //但是如果这个Field被存储了(Stored=YES),那么我们查询别的Field的时候,可以得到这种Field信息
      NO{
          public boolean isIndexed()  { return false; }
          public boolean isAnalyzed() { return false; }
          public boolean omitNorms()  { return true;  }   
      },
      //该Field值需要建索引,而且需要分词
      // 可以通过Field值中的词语进行查询,适合内容查询(全文检索)
      ANALYZED {
          public boolean isIndexed()  { return true;  }
          public boolean isAnalyzed() { return true;  }
          public boolean omitNorms()  { return false; }   	
     },
      //该Field值需要建索引,但不需要分词
      //由于不分词,只能够通过整个值进行查询,适合像商品编号这样的ID值或者单个词语
      NOT_ANALYZED {
          public boolean isIndexed()  { return true;  }
          public boolean isAnalyzed() { return false; }
          public boolean omitNorms()  { return false; }   	
     },
}

 

Document 是Field 的集合(并不是狭隘的文件的含义) 在Lucene中,Document作为数据源的各种属性信息的集合,向Lucene提供原始的要索引的数据。这些数据源不仅可以是文件,也可以是一段字符串、几个数字、甚至一些链接。只要把它们加入到Document对象中,Lucene就可以为这些数据源建立索引。下面的部分Document源码表明:Document主要起到对Field信息进行记录和管理的作用。

 

public final class Document implements java.io.Serializable {
 
    //Field列表
    List<Fieldable> fields = new ArrayList<Fieldable>();
    //在Document中加入Field
    public final void add(Fieldable field) {
         fields.add(field);
    }

    public final void removeField(String name){....}
    public final Field getField(String name) {....}
    .....
}

 

还是上面检索文件的例子,每个文档文件的不同属性信息都被组织成了三个Field对象:path Field、modified Field、content Field。我们可以创建一个Document对象,加入这三个Field,来表示一个文档文件需要被检索的三种数据。

Document doc = new Document();  

doc.add(pathField);
doc.add(modifiedField);
doc.add(contentField);

 

 

总结 :下面的图很清楚的说明Lucene的数据源表示形式

 

举个例子,按照《Lucene体系结构概述》 中代码(IndexFiles.java )对3个txt文件建立索引。Lucene首先将这三个数据源在内存中组织成Document、Field 如下表:

 

Document    Field1 (path)     Field2 (modified)
    Field3 (content)
    1.txt    e:\\....\\1.txt        2010-4-1  I'm a good stud..
    2.txt    e:\\....\\2.txt        2010-4-2  It's me to a fini...
    3.txt    e:\\....\\3.txt        2010-2-11  Hi, Jack me too...

 

Document 和 Field在Lucene中的作用是巨大的。我们都知道Lucene可以对任何形式的数据源建立索引,比如字符串、纯文本、XML、HTML等数据形式。怎么多杂乱无章的数据必须组织成统一有效的结构才能更好的处理,Document / Field 无疑做到了这一点。

 

你可能感兴趣的:(apache,数据结构,Lucene,全文检索,出版)