1. 基本概念
信息检索(IR)是指文档搜索、 文档内信息搜索或者文档相关的元数据搜索等操作。 文档:用于搜索的内容部件。
文档过滤器:将文本格式信息从原始内容中提取出来,便于后期建立搜索引擎文档。如Tika,与数据库的内容连接,DBSight、Hibernate Search、LuSQL、Compass和Oracle/Lucene集成项目。
词汇单元:即分词。词干提取器,如Snowball。
搜索质量主要由查准率(Precision)和查全率(Recall)来衡量。[1]P13 语法检查器: Lucene的 contrib目录提供了两个模块完成此功能。
查询对象: Lucene提供了一个称之为查询解析器(QueryParser),用它可以根据通用查询语法将用户输入的文本处理成查询对象。
查询搜索:査询检索索引并返回与査询语句匹配的文档,结果返回时 按照査询请求来排序。搜索查询组件涵盖了搜索引擎内部复杂的工作机制,Lucene正是 如此,它为你完成这一切。 倒排索引:inverted index
常见的搜索理论模型有如下3种。
■ 纯布尔模型(Pure Boolean model) 文档不管是否匹配查询请求,都不会被评分.在该模型下,匹配文档与评分不相关,也是无序的;一条查询仅获取所有匹配文档集合的一个子集。
■ 向量空间模型(Vector space model)
查询语句和文档都是高维空间的向
量模型,这里每一个独立的项都是一个维度。查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到.
■概率模型(Probabilistic model)在该模型中,采用全概率方法来计算文档和查询语句的匹配概率。
Lucene在实现上采用向量空间模型和纯布尔模型,并能针对具体搜索让你决定采用哪种模型。最后,Lucene返回的文档结果必须用比较经济的方式展现给用户。
搜索范围:涉及分布式搜索,Apache Lucene项目下的Solr和Nutch项目提供了对索引拆分和复制的支持,另Katta和Elastic search。
1.1 Lucene核心类概貌
执行简单的索引过程需要用到以下几个类: ■ IndexWriter ■ Directory ■ Analyzer ■ Document ■ Field
? IndexWriter (写索引)是索引过程的核心组件。这个类负责创建新索引或者打
开 已有索引,以及向索引中添加、删除或更新被索引文档的信息。可以把IndexWriter 看做这样一个对象:它为你提供针对索引文件的写人操作,但不能用于读取或搜索索引。 IndexWriter需要开辟一定空间来存储索引,该功能可以由Directory完成。
? Directory类描述了 Lucene索引的存放位置。它是一个抽象类,它的子类负
责具体指定索引的存储路径。在前面的Indexer例子中,我们用FSDirectory.open方法来获取真实文件在文件系统的存储路径,然后将它们依次传递给IndexWriter类构造方法。
? 文本文件在被索引之前,需要经过Analyzer (分析器)处理。Analyzer是由
IndexWriter 的构造方法来指定的,它负责从被索引文本文件中提取语汇单元,并提出剩下的无用信 息。如果被索引内容不是纯文本文件,那就就需要先
将其转换为文本文档。
? Document (文档)对象代表一些域(Field)的集合。你可以将Document对象
理解 为虚拟文档——比如Web页面、E-mail信息或者文本文件——然后你可以从中取回大量 数据。文档的域代表文档或者和文档相关的一些元数据。文档的数据源(比如数据库记 录、Word文档、书中的某章节等)对于Lucene来说是无关紧要的。Lucene只处理从二 进制文档中提取的以Field实例形式出现的文本。
? 索引中的每个文档都包含一个或多个不同命名的域,这些域包含在Field类
中。 每个域都有一个域名和对应的域值,以及一组选项来精确控制Lucene 索引操作各个域值。文档可能拥有不止一个同名的域。在这种情况下,域的值就按照索引操作顺序添加进去。在搜索时,所有域的文本就好像连接在一起,作为一个文本域来处理。
搜索操作: ■ IndexSearcher ■ Term ■ Query ■ TermQuery ■ TopDocs
? IndexSearcher类用于搜索由IndexWriter类创建的索引:这个类公开了几个
搜 索方法,它是连接索引的中心环节。可以将IndexSearcher类看做一个以只读方式打 开索引的类。它需要利用Directory实例来掌控前期创建的索引,然后才能提供大量 的搜索方法,其中一些方法在它的抽象父类Searcher中实现,最简单的搜索方法是将 单个Query对象和int topN计数作为该方法的参数,并返回一个TopDocs对象。
Directory dir = FSDirectory.open(new File(\; IndexSearcher searcher = new IndexSearcher(dir);
Query q = new TermQuery(new Term(\TopDocs hits - searcher.search(q,10); searcher.close();
? Term对象是搜索功能的基本单元。与Field对象类似,Term对象包含一对字
符串元 素:域名和单词(或域文本值)。注意Term对象还与索引操作有关。然而,由于Term 对象是由Lucene内部创建的,我们并不需要在索引阶段详细了解它们。在搜索过程中 可以创建Term对象,并和TermQuery对象一起使用:
Query q = new TermQuery(new Term(\; TopDocs hits = searcher.search(q, 10);
? Lucene含有许多具体的Query (查询)子类。到目前为止,我们谈到的只是
Lucene 基本的 Query 子类:TermQuery 类。其他的 Query 子类有:BooleanQuery、PhraseQuery、 PrefixQuery 、 PhrasePrefixQuery、 TermRangeQuery 、 NumericRangeQuery、 FilteredQuery和SpanQuery。 它包含了一些非常私用的方法,其中最有趣的当属 setBoost (float) 该方法能使你告知Lucene某个子查询相对其他子査询来说必须对最后的评分有更强贡献。 ? TopDocs类是一个简单的指针容器,指针一般指向前N个排名的搜索结果,
搜索结 果即匹配查询条件的文档。TopDocs会记录前N个结果中每个结果的int docID (可以 用它来恢复文档)和浮点型分数。
1.2 术语
规范化:将字母转换成小写 词干还原:将单词还原为词干形式
词形归并(lemmatization):将单词转换为基本形式 词汇单元(token):从文本流中提取的文本块 项(term):语汇单元与它的域名结合后的产物
2.构建索引
文档是Lucene索引和搜索的原子单位。文档为包含一个或多个域的容器,而域则 依次包含“真正的”被搜索内容。每个域都有一个标识名称,该名称为一个文本值或二 进制值。当你将文档加人到索引中时,可以通过一系列选项来控制Lucene的行为。在 对原始数据进行索引操作时,你得首先将数据转换成
Lucene所能识别的文档和域。在 随后的搜索过程中,被搜索对象则为域值,例如,用户在输人搜索内容“title:lucene” 时,搜索结果则为标题域值包含单词“lucene”的所有文档。
进一步地,Lucene可以针对域进行3种操作。
■ 域值可以被索引(或者不被索引)。如果需要搜索一个域,则必须首先对它进行 索引.被索引的域值必须是文本格式的(二进制格式的域值只能被存储而不能被 索引).在索引一个域时,需要首先使用分析过程将域值转换成语汇单元,然后 将语汇单元加入到索引中.有关索引域值的具体操作选项可以参考[1]2.4.1小节.
■域被索引后,还可以选择性地存储项向量,后者可以看做该域的一个小型反向 索引集合,通过该向量能够检索该域的所有语汇单元.这个机制有助于实现一些高级功能,比如搜索与当前文档相似的文档(更多的高级功能详见[1]5.7小节). 有关控制索引项向量的具体选项请参考[1]2.4.3小节.
■域值可以被单独存储,即是说被分析前的域值备份也可以写进索引中,以便后 续的检索.这个机制可以使你将原始域值展现给用户,比如文档的标题或摘要。 域值的存储选项请参考[1]2.4.2小节.