在我们详细讲述Lucene索引API之前,来看看概念模型的内容。首先我们先从Lucene索引和搜索的基础单位开始,文档和字段(Documents and Fields),然后再看看Lucene和现代数据库模型的一些重要不同。
文档和字段
一个文档是索引用来索引和搜索的最小单位。它实际上是一个包含很多字段的容器,依次保存了真正的内容。每个字段都有一个名字来区分它,一个文本或二进制值,以及一些参数来描述当进行索引的时候,Lucene要对这些字段所做的操作。为了要索引这些未处理过的数据源,你必须要把它们转为文档和字段。之后,在搜索时,在搜索字段的值;举个例子,一个用户搜索"title:lucene"来查找title字段包含短语lucene的所有文档。
从高级别来看,Lucene会对字段进行如下操作
- 索引还是不索引值。如果你要在这个值上进行搜索,那么必须进行索引。文本字段可能被索引(二进制值得字段被存储就可以了)。当一个字段被索引时,在内容中最先提取出标记(token),这个过程叫做分析(analysis),之后这些标记在进入索引中。
- 如果字段被索引了,它也可以存储词向量(term vector)。词向量是个真正的小型反向索引。可以允许你获取这个字段所有的标记(token)。
- 也可以存储这个字段的值,也就是对没有分析过的值进行逐个复制。这样做是为了在后面可以取到这些内容。这对于用户查看没有更改的内容是非常有用的。比如一篇文章的标题。
把原生的内容分解为文档和字段的过程是迭代的,它依赖于应用程序需求的变化。Lucene并不关心哪些字段被使用了以及它们的名字等等。文档通常有很多字段,如,标题,作者,日期,摘要,文章正文,URL,关键词等等。通常的做法是把所有文本的字段的值插入到一个"content"字段中,以及仅仅索引这个字段,但是仍然独立存储这些最初的字段,用来展现。一旦你创建了文档,你就要把它添加到你的索引中。之后,在搜索的时候,你就可以获取符合查询条件的文档并且把存储的字段值展现给用户。
由于数据库和lucene都是存储数据以及可以用来查询。所以人们常常来比较它们。然而它们有很多重要的不同,首先就是lucene灵活的Schema
灵活的schema
不像数据库那样,Lucene并没有一个全局固定的schema。也就是说,每个你添加到索引的文档都是一个空白状态并且可能和它之前的文档完全不同:可能有不同的字段,任意的索引,存储方式以及词向量的参数。并不要求一定要和之前添加的文档一样。甚至可以有相同的字段,不同的参数。
这样是非常强大的:允许使用迭代的方式来创建索引了。可以很快的来索引文档,而不必有先前的设计。如果你要更改字段,可以开始直接添加额外的字段和重新索引先前添加的文档或者重新创建索引。
也就是说,一个单独的索引可以保存不同内容的文档。说个实例,你可能有个文档来保存产品信息,字段是name和price并且也能保存一个人的文档,包含字段name,age和gender。你可能也要有个不能被搜索的meta文档,它存储了索引或者你的应用的meta信息,如索引最后更新时间或者索引的产品目录,但是这些都不会包含在搜索结果中。
数据库和Lucene第二点主要不同是当你索引的时候,需要你对内容进行打散或者反范式。
反范式
你的文档对于Lucene的展现来说,挑战在于如何解决这两个之间的不匹配。举个例子,XML可以通过内置标签来完成一个递归的文档结构。一个数据库可以通过主键和外键来关联其他的表。微软的OLE文档可以嵌入引用其他文档。然而,Lucene文档是平的。当你创建文档时候,递归和关联关系必须反范式化。开源项目,如Hibernate Search,Compass,LuSQL,DBSight,Browse Engine和ORACLE/Lucene集成都有不同的和有趣的方法来反范式化。
现在你已经明白概念级别的Lucene模型文档了。让我们看看更高级别的索引过程。