Lucene中的Analyzer

Lucene中的Analyzer

为了更好地搜索中文,先通过图4-2了解一下在Lucene中通过WhitespaceTokenizer、WordDelimiter Filter、LowercaseFilter处理英文字符串的流程。

 
图4-2  Lucene处理英文字符串流程

Lucene中的StandardAnalyzer对于中文采用了单字切分的方式,这样的结果是单字匹配,如搜索"上海",可能会返回和"海上"有关的结果。

CJKAnalyzer采用了二元覆盖的方式实现。小规模搜索网站可以采用二元覆盖的方法,这样可以解决单字搜索"上海"和"海上"混淆的问题。采用中文分词的方法适用于中大规模的搜索引擎。猎兔搜索提供了一个基于Lucene接口的Java版中文分词系统。

可以对不同的索引列使用不同的Analyzer来切分。例如可以对公司名采用CompanyAnalyzer来分析;对地址列采用AddressAnalyzer来分析。这样可以通过更细分化的切分方式来实现更准确合适的切分效果。

例如把"唐山聚源食品有限公司"拆分成如表4-1所示的结果。

表4-1  公司名拆分结果表

开始位置

结束位置

标注类型

唐山

0

2

City

聚源

2

4

KeyWord

食品

4

6

Feature

有限公司

6

10

Function

这里的开始位置和结束位置是指词在文本中的位置信息,也叫做偏移量。例如"唐山"这个词在"唐山聚源食品有限公司"中的位置是0-2。OffsetAttribute属性保存了词的位置信息;TypeAttribute属性保存了词的类型信息。

切分公司名的流程如图4-3所示。

 
图4-3  Lucene处理公司名流程

 

专门用来处理公司名的CompanyAnalyzer实现代码如下所示:

  1. public class CompanyAnalyzer extends   
  2.    Analyzer {   
  3.     public TokenStream tokenStream   
  4.        (String fieldName, Reader reader) {  
  5.         //调用ComTokenizer切分公司名  
  6.         TokenStream stream = new           
    ComTokenizer(reader);  
  7.         //调用ComFilter后续加工  
  8.         stream = new ComFilter          (stream);  
  9.         return stream;  
  10.     }  
  11. }  

对不同的数据写了不同用途的分析器,需要在同一个索引中针对不同的索引列使用。一般情况下只使用一个分析器。为了对不同的索引列使用不同的分析器,可以使用PerFieldAnalyzerWrapper。在PerFieldAnalyzerWrapper中,可以指定一个默认的分析器,也可以通过addAnalyzer方法对不同的列使用不同的分析器,例如:

  1. PerFieldAnalyzerWrapper aWrapper =  
  2.       new PerFieldAnalyzerWrapper(new CnAnalyzer());  
  3.    aWrapper.addAnalyzer("address", new AddAnalyzer());  
  4.    aWrapper.addAnalyzer("companyName", 
    new CompanyAnalyzer());  

在这个例子中,将对所有的列使用CnAnalyzer,除了地址列使用AddAnalyzer且公司名称列使用CompanyAnalyzer。像其他分析器一样,PerFieldAnalyzerWrapper可以在索引或者查询解析阶段使用。

猜你喜欢

转载自aoyouzi.iteye.com/blog/2085700
今日推荐