AnalyzerUtils的displayTokens(analyzer,text)方法可对文本分析过程进行显示。 AnalyzerDemo可以在命令行显示这一过程。详见[1]P117
4.3 域分析与处理,多值域处理
一个文档可能有多个同名域,这些域建立索引时会附加在一起,如需分离,可继承Analyzer类,并重载getPositionIncrementGap方法,将返回值增加到足够大,以表示两个域相隔较远。
针对不同的特定域使用不同的分析器,需要自己创建分析器,另外也可使用内置工具类 PerFieldAnalyzerWapper。其addAnalyzer方法可针对不同域添加新的
分析器。
只有在索引期间才知道一个域是否被分析过,该域的项一旦被编入索引,就与其他项完全一样。该问题非常重要,参见[1]P137。组合使用KeywordAnalyzer。索引与分析时,均可以对特定域使用特定分析器,这可以减少NOT_ANALYZED_NO_NORMS的使用。
4.4语言分析
对于不同语言的规范化处理,通常需要用到字符过滤类,CharReader、CharStream、CharFilter等。
适用于亚洲语言的分析器,contrib目录中:CJK、 Chinese、 Smart Chinese。
4.5 一些项目中使用的分析技术
Nutch 分析技术: 二元语法技术[1] 4.9节
5.高级搜索技术 5.1 域缓存
使用域缓存可以根据域值对搜索结果进行排序,在后台使用域缓存等。使用域缓存的一个重要限制是所有文档都必须拥有一个与指定域对应的单一域值,因此可能不能处理多值域,需要看版本支持。
域缓存只能用于包含单个项的域.这通常意味着该域在被索引时需要使用参
数Index .NOT_ANALYZED 或 Index . N0T_ANALYZED_N0_N0RMS ,如果使用诸如 Keyword- Analyzer等分析器的话,这些域还是可以被分析的,该分析过程只产生一个语汇单元. 如下使用方式:
如果每个文档都有一个称之为“weight”的域,那么你就可以获得每个文档中该域的域值,操作如下:
float [] weights = FieldCache.DEFAULT.getFloats(reader, \
然后,在需要知道产品文档重量的时候加人引用weights [dOCID]即可。域缓存支 持很多本地数据类型:byte、short、int、long、float, double、string 以及 Stringlndex 类,最后一项包括string值的排序顺序。
域缓存的初次建立耗费较大。只有reader关闭并删除其对应引用时,该缓存才会释放。
5.2 搜索结果排序、按不同语言字符集排序
能对结果进行排序的方法可调用search (Query,Filter,int, Sort)。如果不需要对结果进 行过滤的话,需要将Filter对象置为null。
使用IndexSearcher类的setDefaultFieldSortScoring () 方法,该方法有两个布尔类型参数:doTrackScores和doMaxScore。如果 doTrackScores参数为true,那么每个搜索命中结果都会被进行评分操作。如果 doMaxScore为true,那么程序将对最大分值的搜索命中结果进行评分操作。需要注意 的是,后者通常会耗费更多的系统资源,因为前者只对最有效的搜索结果进行评分操作。 按照相关性排序,默认排序方式。Sort.RELEVANCE 按索引顺序排序,Sort.INDEXORDER
通过域排序,当域整个被索引成单个语汇单元时可用,即不分析。当域内容存储时,可使用如下例的方式:
new Sort(new SortField(\
默认情况下,Lucene排序方向使用的是自然排序方式。对相关度采用降序排列,对其他域采用升序排列。需进行倒序处理,如下: new Sort(new SortField(\
需要对多个域进行排序时,创建Sort对象时,加入多个SortField对象。SortField 对象都包含域名、域类型和反向排序标志位。另外,SortField对象还包含集中域类型的常 量,它们是 SCORE、DOC、STRING, BYTE, SHORT、INT、LONG、FLOAT 和 DOUBLE。 其中SCORE和DOC常量是用于针对相关性和文档ID进行排序的特殊类型。
按照SortField.STRING类型排序时,程序内部会默认地调用String.compareTo() 方法来确定排列次序。不过,如果需要另一种不同的排列顺序,SortField类允许你通过制定一个本地化的方法来达到这个目的。Collator对象是通过Collator.getInstance(Locale)方法来初始化的,而Collator.compare()方法则用于决定排序方式。在指定Locale对象时,有两个可重载的SortField初始化方法可用: public SortField (String field, Locale locale)
public SortField (String field, Locale locale, boolean reverse)
这两个构造方法所创建的对象都是按照SortField.STRING类型排序的SortField对 象,因为Locale对象只适用于字符类型的排序,而不能用于数值类型。
5.3 MultiPhraseQuery
可用来将不同位置的相似匹配进行组合。如:
MultiPhraseQuery query = new MultiPhraseQuery(); query.add(new Term[]{ new Term(\允许其中一个项被首 new Term(\ });
query.add(new Term(\
先匹配
5.4 针对多个域的查询
第一种实现方式就是创建多值的全包含域来对所有域的文本进行索引。一定要在添加域值时对域值之间的空格进行位置增量处理,这样能避免程序错误地将两个域之间的域值进行査询匹配操作。然后程序就可以对这个全包含域进行搜索了。该方案有一些缺陷:你不能直接对每个域的加权进行控制,并且假如你还分开使用这些域的话,它会浪费磁盘空间。
第二种实现方式就是使用MultiFieldQueryParser,它是QueryParser的子类。它在会在后台程序中实例化一个QueryParser对象,用来针对每个域进行查询表达式的解析,然后使用BooleanQuery将查询结果合并起来。当程序向BooleanQuery添加查询子句时,默认操作符OR被用于最简单的解析方法中。为了实现更好的控制,布尔操作符可以使用BooleanClause的常量指定给每个域,如果需要指定的话可以使用 BooleanClause.Occur.MUST ,如果禁止指定可以使用 BooleanClause. Occur.MUST_NOT,或者普通情况为 BooleanClause.Occur. SHOULD。该方法用于复杂查询时,情况会更加复杂,需要分析以确定查询模式正确。
用于自动査询多值域的第三种实现方式就是使用髙级DisjunctionMaxQuery类,它会封装一个或多个任意的查询,将匹配的文档进行OR操作。你可以使用 BooleanQuery完成这个功能,正如MultiFieldQueryParser所完成的那样,但 DisjunctionMaxQuery的有趣之处在于它的评分方式:当某个文档匹配到多于一条查询时,该类会将这个文档的评分记为最髙分,而与BooleanQuery相比,后者会将所有匹配的评分相加。这样能产生更好的终端用户相关性。
DisjunctionMaxQuery还包含一个可选的仲裁器,因此所有处理都是平等的,一个 匹配更多查询的文档能够获得更高的评分。为了用DisjunctionMaxQuery进行多值域 査询,你需要创建一个新的基于域的Query,该Query得包含所有需要用到的域,然后 使用DisjunctionMaxQuery的add方法来包含这个Query。
5.5 跨度查询
即域中的启示语汇单元与终止语汇单元的位置。在搜索期间,跨度查询所跟踪的文档要比匹配的文档要多:每个单独的跨度(每个域可包含多个跨度)都会被跟踪。与TermQuery做个比较,TermQuery只是对文档进行简单的匹配操作,而SpanTermQuery除了完成这个功能外,还会保留每个匹配文档 对应的项位置信息。总的来说,跨度查询是一种计算密集型操作。