scene 项目分析报告
Lucene 项目分析报告
目录 简介 功能模块 21文档( Document)模块 211功能 212使用方法 213设计思路 22索引(ndex)模块 221功能 22使用方法 223设计思路 23查询( Search)模块 功能. 232使用方法 233设计思路 24语汇分析( Analysis模块 241功能 242使用方法… 243设计思路 25存储( store)模块… 1功能 252使用方法 253设计思路 3综合应用 4总结
目录 1 简介...........................................................................................................................................3 2 功能模块...................................................................................................................................3 2.1 文档(Document)模块 ...................................................................................................4 2.1.1 功能...................................................................................................................4 2.1.2 使用方法...........................................................................................................4 2.1.3 设计思路...........................................................................................................5 2.2 索引(Index)模块 ...........................................................................................................6 2.2.1 功能...................................................................................................................7 2.2.2 使用方法...........................................................................................................7 2.2.3 设计思路...........................................................................................................9 2.3 查询(Search)模块 .........................................................................................................9 2.3.1 功能...................................................................................................................9 2.3.2 使用方法.........................................................................................................10 2.3.3 设计思路.........................................................................................................10 2.4 语汇分析(Analysis)模块 .............................................................................................11 2.4.1 功能.................................................................................................................11 2.4.2 使用方法.........................................................................................................12 2.4.3 设计思路.........................................................................................................12 2.5 存储(store)模块..........................................................................................................13 2.5.1 功能.................................................................................................................13 2.5.2 使用方法.........................................................................................................13 2.5.3 设计思路.........................................................................................................14 3 综合应用.................................................................................................................................15 4 总结.........................................................................................................................................15
1简介 在介绍 Lucene之前,首先,要介绍一下全文检索这个重要的概念,那么什么是全文检 索呢? 全文检索,就是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索 引,指明该词在文章中出现的次数和位置,当用户査询时,检索程序就根据事先建立的索引 进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表 查字的过程 其次, Lucene是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检 索引擎,而是一个全文检索引擎的架构,提供了完整的査询引擎和索引引擎,部分文本分析 引擎(英文与德文两种西方语言)。 Lucene的目的是为软件开发人员提供一个简单易用的工 具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检 索引擎。 Lucene属于 apache软件基金会 jakarta项目组的一个子项目。 2功能模块 经过一个学期对 Lucene项目的功能及源码的研究,本项目小组发现再 Lucene中的核心 类库应该包括以下几个方面: Document、ndex、 Search、 Analyzer、 Store,如下表所示: 核心包名称 解释 Document类是 Lucene中的文件最小单元,与文件系统中存在的每个 文件有一一对应的关系,通过 Lucene内部定义的Feld(域)概念 将一个文件中划分为多个部分,分别提取出每一块的关键内容进行索 引记录。 Index ndex包将所有需要搜索的数据源进行再加工,形成了适于 Lucene的 搜索操作的文件结构,去除了一些不可能作为搜索关键的词语,减少 了信息检索量,从而提高了信息检索的效率,通过不断的增减索引内 容,达到与原始数据源同步的目的 Search Search功能的实现是基于索引文件的建立,通过对索引文件的检索达 到真正搜索的目的, Lucene项目内部为搜索操作提供了多种实现方 法,包括:项搜索、范围搜索、字符串前缀搜索、短语搜索、组合搜 索、通配符搜索、类似项搜索等。 Analyzer Analyzer功能是在索引和搜索两本分的基础上产生的,是为了辅助索 引创建和搜索过程而产生的,在整个 Lucene项目中,语汇分析这个 模块最能体现出其关于搜索的特性。 Store Store的功能也在于加强 Lucene的搜索效率,但是与 Analyzer不同的 是,它重点在研究如何利用计算机的内存容量和文件系统的存储空间 来提高搜索效率,具体的方法包括:缓存查找结果、在内存中创建索 引等 本文档将按照这五个功能的先后顺序对 Lucene的开源项目进行详细阐述,并且在其中 增加项目小组成员对不同模块的分析内容,对项目中已有的设计模式的思想进行抽象和概括
1 简介 在介绍 Lucene 之前,首先,要介绍一下全文检索这个重要的概念,那么什么是全文检 索呢? 全文检索,就是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索 引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引 进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表 查字的过程。 其次,Lucene 是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检 索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析 引擎(英文与德文两种西方语言)。Lucene 的目的是为软件开发人员提供一个简单易用的工 具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检 索引擎。Lucene 属于 apache 软件基金会 jakarta 项目组的一个子项目。 2 功能模块 经过一个学期对 Lucene 项目的功能及源码的研究,本项目小组发现再 Lucene 中的核心 类库应该包括以下几个方面:Document、Index、Search、Analyzer、Store,如下表所示: 核心包名称 解释 Document Document 类是 Lucene 中的文件最小单元,与文件系统中存在的每个 文件有一一对应的关系,通过 Lucene 内部定义的 Field(域)概念, 将一个文件中划分为多个部分,分别提取出每一块的关键内容进行索 引记录。 Index Index 包将所有需要搜索的数据源进行再加工,形成了适于 Lucene 的 搜索操作的文件结构,去除了一些不可能作为搜索关键的词语,减少 了信息检索量,从而提高了信息检索的效率,通过不断的增减索引内 容,达到与原始数据源同步的目的。 Search Search 功能的实现是基于索引文件的建立,通过对索引文件的检索达 到真正搜索的目的,Lucene 项目内部为搜索操作提供了多种实现方 法,包括:项搜索、范围搜索、字符串前缀搜索、短语搜索、组合搜 索、通配符搜索、类似项搜索等。 Analyzer Analyzer 功能是在索引和搜索两本分的基础上产生的,是为了辅助索 引创建和搜索过程而产生的,在整个 Lucene 项目中,语汇分析这个 模块最能体现出其关于搜索的特性。 Store Store 的功能也在于加强 Lucene 的搜索效率,但是与 Analyzer 不同的 是,它重点在研究如何利用计算机的内存容量和文件系统的存储空间 来提高搜索效率,具体的方法包括:缓存查找结果、在内存中创建索 引等。 本文档将按照这五个功能的先后顺序对 Lucene 的开源项目进行详细阐述,并且在其中 增加项目小组成员对不同模块的分析内容,对项目中已有的设计模式的思想进行抽象和概括
21文档[ Document模块 在 Lucene重, Document是承载数据的实体,包含一些域(Fied)的集合相当于一个虚 拟的文档,比如:一个web页面、一个Ema消息或者一个文本文件等,从中可以提取出大 量的数据。一个文档的域代表文档或者和文档相关的一些源数据。文档数据的数据源对于 Lucene来说是无关紧要的,像作者、标题、主题、修改日期等元数据都作为文档的不同的 域被单独存储并索引。 Document对象中有一个更小的概念,是 Lucene为了更加有效的分析文档内容而提出 的一域( Field),每一个域都对应一段数据,这些数据都是在搜索过程中可能会被查询或者 在索引中被检索的,域的分类主要有一下四种 域类型 解释 Keyword域 不需要被分析,会逐字地被索引并存储,适用于需要被全部保留的域 如:URL、文件系统路径、日期、个人姓名等 UnIndex域 不需要被分析和索引,但是会被存储在索引文件中,适用于需要和搜索 结果一起被显示出来的而不会被用户直接搜索的数据,如URL或者数据 库的主键等 UnStored域 需要被分析和索引,但是不会被存储到索引文件中,适用于不需要原始 形式的大量的数目索引文本,例如:网页的正文等 Text域 需要被分析和索引,能够被搜索。 211功能 由于 Document是 Lucene中承载数据的实体这个特性,那么同事也决定了它的功能是 抽取数据源中的有用的数据,以域的形式保存在数据实体中,然后再将其添加到索引中去。 从这个角度来看, Document的功能范围直接影响到 Lucene可以进行操作的数据源的范围 因为 Document本身只能对 java. lang String和 java. io. Reader两种对象进行处理,所以 Lucene 只能处理文本,那么对非文本文件的处理工作需要利用相关工具进行二次处理,转化为文本 文件,才能进行操作 212使用方法 在实际的使用过程中,通常都需要对 Lucene中的 Document类进行重写,以满足在效 率和作用范围的要求。在本项目小组研究研究过程中用到的编写的程序中,建立了自己的 File Document类,对 Lucene自带的 Document操作进行封装,创建了关于这个文件的三个域, 分别为:path(文件路径)、 modified(修改时间)、 contents(文件内容),从而把搜索信息 和结果限制在这三方面的内容中。具体信息请参考如下代码片段:
2.1 文档(Document)模块 在 Lucene 重,Document 是承载数据的实体,包含一些域(Field)的集合相当于一个虚 拟的文档,比如:一个 web 页面、一个 Email 消息或者一个文本文件等,从中可以提取出大 量的数据。一个文档的域代表文档或者和文档相关的一些源数据。文档数据的数据源对于 Lucene 来说是无关紧要的,像作者、标题、主题、修改日期等元数据都作为文档的不同的 域被单独存储并索引。 Document 对象中有一个更小的概念,是 Lucene 为了更加有效的分析文档内容而提出 的―域(Field),每一个域都对应一段数据,这些数据都是在搜索过程中可能会被查询或者 在索引中被检索的,域的分类主要有一下四种: 域类型 解释 Keyword 域 不需要被分析,会逐字地被索引并存储,适用于需要被全部保留的域, 如:URL、文件系统路径、日期、个人姓名等。 UnIndex 域 不需要被分析和索引,但是会被存储在索引文件中,适用于需要和搜索 结果一起被显示出来的而不会被用户直接搜索的数据,如 URL 或者数据 库的主键等。 UnStored 域 需要被分析和索引,但是不会被存储到索引文件中,适用于不需要原始 形式的大量的数目索引文本,例如:网页的正文等。 Text 域 需要被分析和索引,能够被搜索。 2.1.1 功能 由于 Document 是 Lucene 中承载数据的实体这个特性,那么同事也决定了它的功能是 抽取数据源中的有用的数据,以域的形式保存在数据实体中,然后再将其添加到索引中去。 从这个角度来看,Document 的功能范围直接影响到 Lucene 可以进行操作的数据源的范围, 因为 Document 本身只能对 java.lang.String 和 java.io.Reader 两种对象进行处理,所以 Lucene 只能处理文本,那么对非文本文件的处理工作需要利用相关工具进行二次处理,转化为文本 文件,才能进行操作。 2.1.2 使用方法 在实际的使用过程中,通常都需要对 Lucene 中的 Document 类进行重写,以满足在效 率和作用范围的要求。在本项目小组研究研究过程中用到的编写的程序中,建立了自己的 FileDocument类,对Lucene自带的Document操作进行封装,创建了关于这个文件的三个域, 分别为:path(文件路径)、modified(修改时间)、contents(文件内容),从而把搜索信息 和结果限制在这三方面的内容中。具体信息请参考如下代码片段:
// make a new, empty document Document doc new Document (i / Add the path of the file as a field named "path". Use a field that is indexed (i.e. searchable), but don't tokenize the field into WOras doc. add (new Field("path",f getPath(), Field. store. YES, Field Index. UN TOKENIZED)) / Add the last modified date of the file a field named "modified" Use, a field that is indexed (i.e. searchable), but don't tokenize the field doc. add (new Field("modified", DateTools. time Tostring(f. lastModified(), DateTools Resolution MINUTE) Field. store. YES, Field. Index. UN TOKENIZED))i / Add the contents of the file to a field named "contents f a Reader, so that the text of the file is tokenized and indexed, but not stored. Note that FileReader expects the file to be in the system's default encoding. If that 's not the case searching for special characters will fail doc. add (new Field(" contents", new FileReader(f))) / return the document return doci 213设计思路 从 Document的使用方法中,看出它唯一的操作就是将 Field嵌入其中,并且为不同的 Field 命名和设定类型,所以从这个角度考虑,在 Document内部存在一个储存 Field的链表,对 每次加入的Fed进行记录,UML类图如下
// make a new, empty document Document doc = new Document(); // Add the path of the file as a field named "path". Use a field that is indexed (i.e. searchable), but don't tokenize the field into words. doc.add(new Field("path", f.getPath(), Field.Store.YES, Field.Index.UN_TOKENIZED)); // Add the last modified date of the file a field named "modified". Use, a field that is indexed (i.e. searchable), but don't tokenize the field into words. doc.add(new Field("modified", DateTools.timeToString(f.lastModified(), DateTools.Resolution.MINUTE), Field.Store.YES, Field.Index.UN_TOKENIZED)); // Add the contents of the file to a field named "contents". Specify a Reader, so that the text of the file is tokenized and indexed, but not stored. Note that FileReader expects the file to be in the system's default encoding. If that's not the case searching for special characters will fail. doc.add(new Field("contents", new FileReader(f))); // return the document return doc; 2.1.3 设计思路 从 Document 的使用方法中,看出它唯一的操作就是将 Field 嵌入其中,并且为不同的 Field 命名和设定类型,所以从这个角度考虑,在 Document 内部存在一个储存 Field 的链表,对 每次加入的 Field 进行记录,UML 类图如下:
不难看出,在 Document类层次体系结构中, Document和Feld之间存在这组合关系,它们 之间的设计模式为 Composite pattern,即, Document通过组合Feld的来作为数据源的载体 每一个Feld来存储具体的数据信息。这样设计的好处是:将将数据拆分成为细小的块,对 不同类型的块采取不同的操作方式,提高效率,同时,将所有的小块聚集在一个大模块中 方便用户管理。 22索引(ndex)模块 Lucene中的索引操作是发生在整个搜索过程中的最开始阶段。在进行搜索之前,必须 预先完成对数据源的索引操作,从宏观上讲,整个索引操作主要分为以下几个步骤:首先, 将数据转换为文本,其次,分析文本,最后,将分析过的文本保存到索引库中,具体流程如 下图所示 HTML PDF MS Word doc Parser Parser Parser Analysis 在 Lucene的索引模块中的核心操作类有 IndexReader和 ndexWriter两个,它们分别实现了 对索引库的读取、删除和修改操作,详细信息参见下表: 「类 作用 ndexReader对索引库中的索引文件进行查找、读取、删除等操作。 ndexwriter对索引库中的索引文件进行添加、优化、合并等操作
不难看出,在 Document 类层次体系结构中,Document 和 Field 之间存在这组合关系,它们 之间的设计模式为 Composite pattern,即,Document 通过组合 Field 的来作为数据源的载体, 每一个 Field 来存储具体的数据信息。这样设计的好处是:将将数据拆分成为细小的块,对 不同类型的块采取不同的操作方式,提高效率,同时,将所有的小块聚集在一个大模块中, 方便用户管理。 2.2 索引(Index)模块 Lucene 中的索引操作是发生在整个搜索过程中的最开始阶段。在进行搜索之前,必须 预先完成对数据源的索引操作,从宏观上讲,整个索引操作主要分为以下几个步骤:首先, 将数据转换为文本,其次,分析文本,最后,将分析过的文本保存到索引库中,具体流程如 下图所示: 在 Lucene 的索引模块中的核心操作类有 IndexReader 和 IndexWriter 两个,它们分别实现了 对索引库的读取、删除和修改操作,详细信息参见下表: 类 作用 IndexReader 对索引库中的索引文件进行查找、读取、删除等操作。 IndexWriter 对索引库中的索引文件进行添加、优化、合并等操作
221功能 索引操作除了包含向索引库中添加文档外,还可以从索引中移出或者更新文档,同时, 能够修改索引过程中的一些参数,从而调整索引中几个方面的特性以满足具体的需要。并发 性、线程安全性以及锁机制方面的内容,在多线程的应用程序活多进程的操作系统中,对于 Lucene来讲是非常重要的。索引主要功能的实现都是通过 Indexwriter和 IndexReader实现 的,前者在实现索引添加功能主要是通过其派生类 Documentwriter、 TermInfoswriter和 Fⅰ eldsWriter分别以 Document、Term、 Field为操作单元来完成的;后者在实现索引査找功能 主要是通过 Segment Reader、 FieldsReader分别以 Segment、Feld为操作单元来完成的。类 之间的关系图如下所示 etUs Posting Table: java utiL Hasht oindexReadero wa util. Hashtag nlerd org. apache lucene index (1) 222使用方法 在实际中使用 Indexwriter的过程中,不止要对单个文件的信息创建索引文件,通常情 况下,要对某个文件夹下的所有文件及其子文件夹下的所有文件信息建立索引,这就需手动 的递归添加所有文件至索引库中。在下面的源代码中,这个过程由 indexDocs方法来实现 由于 Lucene的索引必须要求文件在系统中有可读的权限,所以在建立索引之前要检测其是 否拥有读的权限。以下的代码片段部分详细描述了 ndexWriter在创建索引中的具体使用步 骤,如下
2.2.1 功能 索引操作除了包含向索引库中添加文档外,还可以从索引中移出或者更新文档,同时, 能够修改索引过程中的一些参数,从而调整索引中几个方面的特性以满足具体的需要。并发 性、线程安全性以及锁机制方面的内容,在多线程的应用程序活多进程的操作系统中,对于 Lucene 来讲是非常重要的。索引主要功能的实现都是通过 IndexWriter 和 IndexReader 实现 的,前者在实现索引添加功能主要是通过其派生类 DocumentWriter、TermInfosWriter 和 FieldsWriter 分别以 Document、Term、Field 为操作单元来完成的;后者在实现索引查找功能 主要是通过 SegmentReader、FieldsReader 分别以 Segment、Field 为操作单元来完成的。类 之间的关系图如下所示: 2.2.2 使用方法 在实际中使用 IndexWriter 的过程中,不止要对单个文件的信息创建索引文件,通常情 况下,要对某个文件夹下的所有文件及其子文件夹下的所有文件信息建立索引,这就需手动 的递归添加所有文件至索引库中。在下面的源代码中,这个过程由 indexDocs 方法来实现, 由于 Lucene 的索引必须要求文件在系统中有可读的权限,所以在建立索引之前要检测其是 否拥有读的权限。以下的代码片段部分详细描述了 IndexWriter 在创建索引中的具体使用步 骤,如下:
try IndexWriter writer new IndexWriter(INDEX DIR, new StandardAnalyzer(), true)i System. out. println ("Indexing to directory !"+ INDEX DIR+ indexDocs(writer, docDir)i System. out. println("Optimizing.. writer lize() el. c Date end new Dated System. out. println(end getTime()- start getTime() +total milliseconds " )i 1 catch (IOException e) System. out. printin(" caught a+e getclass() +"\n with message: "+e getMessage())i static void index DoCs(IndexWriter writer, File file)throws IOException // do not try to index files that cannot be read i£(fi1e. canread()) if (file. isDirectory ())i String[] files file list( / an Io error could occur if (files ! null) for (int i =0; i< files. length; i++) indexDocs(writer, new File(file, files [i]) else System. out. println ("adding "t file)i ry I riter. addDocument(FileDocument Document(file)) // at least on windows, some temporary files raise this exception with an"access denied" message checking if the file can be read doesn't help catch (FileNot FoundException fnfe)
try { IndexWriter writer = new IndexWriter(INDEX_DIR, new StandardAnalyzer(), true); System.out.println("Indexing to directory '" + INDEX_DIR + "'..."); indexDocs(writer, docDir); System.out.println("Optimizing..."); writer.optimize(); writer.close(); Date end = new Date(); System.out.println(end.getTime() - start.getTime() + " total milliseconds"); } catch (IOException e) { System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); } static void indexDocs(IndexWriter writer, File file) throws IOException { // do not try to index files that cannot be read if (file.canRead()) { if (file.isDirectory()) { String[] files = file.list(); // an IO error could occur if (files != null) { for (int i = 0; i < files.length; i++) { indexDocs(writer, new File(file, files[i])); } } } else { System.out.println("adding " + file); try { writer.addDocument(FileDocument.Document(file)); } // at least on windows, some temporary files raise this exception with an "access denied" message checking if the file can be read doesn't help catch (FileNotFoundException fnfe) { ; } } } }
223设计思路 在上面所讲的创建索引的过程中,有一步是对索引进行优化,即 Indexwriter类调用 “ Optimize”方法,这就是索引优化过程,这个方法表面上调用简单,实际上隐藏了 Lucene 内部的许多实现细节,通常,用户是不必关系优化的内部实现的。除非特别需要,用户允许 使用 Lucene内部提供的优化方式,进行搜索引擎加速。下面将对 Lucene内部索引优化过程 进行详细的阐述 在索引的优化处理中, Lucene的内部系统采用了 Segment分段的概念,进行索引文件 的组织。 Lucene中对段的区分是通过不同的文件名后缀来实现的,索引是由一个或多个段 ( Segment)组成,而每个段又是由多个索引文件组成,属于同一个段的索引文件具有相同 的前缀名以及不同的后缀名,每一个段都可以被看作为一个子索引。因此,创建索引的过程 就是利用 Indexwriter类中 add Document( Document)方法将多个文档添加到索引库中。 Lucene支持两种索引结构:多文件索引( multifile indexex)和复合索引( compound indexer),这两者之间惟一的差别就是索引目录的内容。与多索引文件需要到开并读取的文 件数目相比,访问符合索引时需要打开的文件更少,消耗的系统资源更少。符合索引减少了 索引文件的数量,但是段、文档、域和项的概念仍然适用。复合索引中每个段包含一个ct 文件将多索引文件的每个段的多个不同的文件封装了起来。 总之,索引结构的基本原理包括性能最大化和资源利用最小化两个部分,在 Lucene中 所有的索引结构都是按照这个原则进行设计的 23查询〔 Search)模块 Lucene中能够快速的提供相关度搜索的功能主要是依靠 search包中的αuery类系实现 的,在索引建立完成之时,通过 Indexsearch调用 Query类对索引的检索操作,返回一个有 序的Hts对象结果的集合( Collection)。 Lucene的主要搜索AP,如下所示 类 IndexSearcher 搜索操作的主入口。所有的搜索操作都是通过 Indexsearch实例使 用一个重载的 search方法来实现的。 uey(及其子类)具体的 Query子类为每一种特定类型的查询进行了逻辑上的封装 Query实例被传递到 IndexSearcher的 search中。 Hits 提供对搜索结果的访问。Hits对象由 IndexSearcher的 search方法 231功能 首先,介绍査询操作的一般步骤,如下 査询者输入査询条件,条件之间可以通过特定运算符进行运算,比如查询希望查询到与 “中国”和“北京”相关的记录,但不希望结果中包括“海淀区中关村”,于是输入条 件为“中国+北京海淀区中关村”; 2.查询条件被传达到查询分析器中,分析器将将对“中国+北京-海淀区中关村”进行分析, 首先分析器解析字符串的连接符,即这里的加号和减号,然后对每个词进行切词,一般 最小的词元是两个汉字,则中国和北京两个词不必再切分,但对海淀区中关村需要切分
2.2.3 设计思路 在上面所讲的创建索引的过程中,有一步是对索引进行优化,即 IndexWriter 类调用 “Optimize”方法,这就是索引优化过程,这个方法表面上调用简单,实际上隐藏了 Lucene 内部的许多实现细节,通常,用户是不必关系优化的内部实现的。除非特别需要,用户允许 使用 Lucene 内部提供的优化方式,进行搜索引擎加速。下面将对 Lucene 内部索引优化过程 进行详细的阐述。 在索引的优化处理中,Lucene 的内部系统采用了 Segment 分段的概念,进行索引文件 的组织。Lucene 中对段的区分是通过不同的文件名后缀来实现的,索引是由一个或多个段 (Segment)组成,而每个段又是由多个索引文件组成,属于同一个段的索引文件具有相同 的前缀名以及不同的后缀名,每一个段都可以被看作为一个子索引。因此,创建索引的过程 就是利用 IndexWriter 类中 addDocument(Document)方法将多个文档添加到索引库中。 Lucene 支持两种索引结构:多文件索引(multifile indexex)和复合索引(compound indexer),这两者之间惟一的差别就是索引目录的内容。与多索引文件需要到开并读取的文 件数目相比,访问符合索引时需要打开的文件更少,消耗的系统资源更少。符合索引减少了 索引文件的数量,但是段、文档、域和项的概念仍然适用。复合索引中每个段包含一个 cfs 文件将多索引文件的每个段的多个不同的文件封装了起来。 总之,索引结构的基本原理包括性能最大化和资源利用最小化两个部分,在 Lucene 中 所有的索引结构都是按照这个原则进行设计的。 2.3 查询(Search)模块 Lucene 中能够快速的提供相关度搜索的功能主要是依靠 search 包中的 Query 类系实现 的,在索引建立完成之时,通过 IndexSearch 调用 Query 类对索引的检索操作,返回一个有 序的 Hits 对象结果的集合(Collection)。Lucene 的主要搜索 API,如下所示: 类 用途 IndexSearcher 搜索操作的主入口。所有的搜索操作都是通过 IndexSearch 实例使 用一个重载的 search 方法来实现的。 Query(及其子类) 具体的 Query 子类为每一种特定类型的查询进行了逻辑上的封装。 Query 实例被传递到 IndexSearcher 的 search 中。 Hits 提供对搜索结果的访问。Hits 对象由 IndexSearcher 的 search 方法 返回。 2.3.1 功能 首先,介绍查询操作的一般步骤,如下: 1. 查询者输入查询条件,条件之间可以通过特定运算符进行运算,比如查询希望查询到与 “中国”和“北京”相关的记录,但不希望结果中包括“海淀区中关村”,于是输入条 件为“中国+北京-海淀区中关村”; 2. 查询条件被传达到查询分析器中,分析器将将对“中国+北京-海淀区中关村”进行分析, 首先分析器解析字符串的连接符,即这里的加号和减号,然后对每个词进行切词,一般 最小的词元是两个汉字,则中国和北京两个词不必再切分,但对海淀区中关村需要切分
假设根据切词算法,把该词切分为“海淀区”和“中关村”两部分,则最后得到的查询 条件可以表示为:“中国”AND“北京” AND NOT(“海淀区”AND“中关村”) 3.査询器根据这个条件遍历索引树,得到査询结果,并返回结果集,返回的结果集类似于 JDBC中的 Resultset 4.将返回的结果集显示在查询结果页面,当点击某一条内容时,可以链接到原始网页,也 可以打开全文检索库中存储的网页内容。 其次,从以上的操作步骤中可以看出, Lucene中的查询机制是通过不同类型的 Query子类 来实现的,通常用到的查询类型包括 TermQuery、 RangeQuery、 BooleanQuery等; 232使用方法 Query的产生是基于用户输入的査询语句,依据特定的分析器 Analyzer,由查询转换器 QueryParser实现的,分析器的概念将在下一节进行详细阐述。在完整的查询条件 Query生 成之后,由 IndexSearch对这些查询条件对索引进行搜索,返回查询结果Hts,通过遍历的 方式将所有结果都显示出来,这样用户就可以知道具体搜索结果的内容了。 Query query parser parse(line)i ystem out println ("Searching for:+ query tostring(field))i Hits hits searcher search(query) // repeat time as benchmark for 1=0; i< repeat; i++)i archer. search(query)i Date end ew Date(i System. out. println("Time: +(end getTime()-start getTime())+ms") System. out. println(hits. length()+" total matching documents") 233设计思路 在关于搜索过程中, Lucene的设计在査询转换、评分策略。查询类体系的设计都是十 分巧妙的,这里,只介绍关于查询类体系的设计过程。关于 Query体系的设计,最大的特点 就是能够体现出在搜索过程中,用户可能采取的所有搜索模式,并且将这些模式进行布尔逻 辑组合,尽可能反映出用户的真实搜索意图。详细的 Query类体系结构如下图所示:
假设根据切词算法,把该词切分为“海淀区”和“中关村”两部分,则最后得到的查询 条件可以表示为:“中国” AND “北京” AND NOT(“海淀区” AND “中关村”)。 3. 查询器根据这个条件遍历索引树,得到查询结果,并返回结果集,返回的结果集类似于 JDBC 中的 ResultSet。 4. 将返回的结果集显示在查询结果页面,当点击某一条内容时,可以链接到原始网页,也 可以打开全文检索库中存储的网页内容。 其次,从以上的操作步骤中可以看出,Lucene 中的查询机制是通过不同类型的 Query 子类 来实现的,通常用到的查询类型包括 TermQuery、RangeQuery、BooleanQuery 等; 2.3.2 使用方法 Query 的产生是基于用户输入的查询语句,依据特定的分析器 Analyzer,由查询转换器 QueryParser 实现的,分析器的概念将在下一节进行详细阐述。在完整的查询条件 Query 生 成之后,由 IndexSearch 对这些查询条件对索引进行搜索,返回查询结果 Hits,通过遍历的 方式将所有结果都显示出来,这样用户就可以知道具体搜索结果的内容了。 Query query = parser.parse(line); System.out.println("Searching for: " + query.toString(field)); Hits hits = searcher.search(query); if (repeat > 0) { // repeat & time as benchmark Date start = new Date(); for (int i = 0; i < repeat; i++) { hits = searcher.search(query); } Date end = new Date(); System.out.println("Time:+(end.getTime()-start.getTime())+"ms"); } System.out.println(hits.length() + " total matching documents"); 2.3.3 设计思路 在关于搜索过程中,Lucene 的设计在查询转换、评分策略。查询类体系的设计都是十 分巧妙的,这里,只介绍关于查询类体系的设计过程。关于 Query 体系的设计,最大的特点 就是能够体现出在搜索过程中,用户可能采取的所有搜索模式,并且将这些模式进行布尔逻 辑组合,尽可能反映出用户的真实搜索意图。详细的 Query 类体系结构如下图所示: