[ Lucene 分词 ] - lucene analyzer 体系结构一览

分词这块内容往往是做搜索的入门级内容,例如我们刚接触搜索的时候,经常会碰到“想要检索的检索不到”的问题,这时得对分词有个大概的了解了。

这里是简要分析,因此我用的是lucene1.9来分析(目前看的源码主要也是1.9版本,虽然都快出4.0了)

 

一)体系结构

首先我们了解两组类结构,一是Analyzer,二是TokenStream。

图1:analyzer类结构

图2:TokenStream类结构

TokenStream有两个直接子类:TokenFilter和Tokenizer,其最主要的区别是:TokenFilter接收一个TokenStream进行再加工;Tokenizer接收一个Reader进行基础性分词。

然后Analyzer是一个包装器,一般选用一个Tokenizer,外加多个TokenFilter(当然也可以不加TokenFilter)构成一个分词器。

细细想想和java I/O的设计有点类似。

 

举例:StandardAnalyzer算是最复杂的分词器了(在1.9中),他的组装方式如下:

TokenStream result = new StandardTokenizer(reader);
result = new StandardFilter(result);
result = new LowerCaseFilter(result);
result = new StopFilter(result, stopSet);

不难看出,StandardAnalyzer首先选用StandardTokenizer进行分词,然后逐一通过StandardFilter、LowerCaseFilter、StopFilter进行再加工处理。

 

二)Tokenizer

Tokenizer就是按照指定规则将Reader划分成一个个词(Token),例如WhitespaceTokenizer就是按照空格进行划分,LetterTokenizer就是按照是不是字母进行划分,KeywordTokenizer就是将整个reader的内容作为一个token,等等。

对于CharTokenizer(LetterTokenizer、KeywordTokenizer)都是基于字符进行判断的,因此有一个方法比较重要,就是isTokenChar(char c)。

简单看看KeywordTokenizer的源码,如下:

  public Token next() throws IOException {
    if (!done) {
      done = true;
      StringBuffer buffer = new StringBuffer();
      int length;
      while (true) {
        length = input.read(this.buffer);
        if (length == -1) break;

        buffer.append(this.buffer, 0, length);
      }
      String text = buffer.toString();
      return new Token(text, 0, text.length());
    }
    return null;
  }

他将输入的内容作为一个整词输出。

 

三)TokenFilter

TokenFilter是对Tokenizer的再加工,包括字符小写(LowerCaseFilter)、去停用词(StopFilter)等。

LowerCaseFilter源码如下:

  public final Token next() throws IOException {
    Token t = input.next();

    if (t == null)
      return null;

    t.termText = t.termText.toLowerCase();

    return t;
  }

这里不需过多解释,强调一下TokenFilter的输入时一个TokenStream,他们可以穿起来,形成一条加工线。

StopFilter源码如下:

  /**
   * Returns the next input Token whose termText() is not a stop word.
   */
  public final Token next() throws IOException {
    // return the first non-stop word found
    for (Token token = input.next(); token != null; token = input.next())
    {
        String termText = ignoreCase ? token.termText.toLowerCase() : token.termText;
        if (!stopWords.contains(termText))
          return token;
    }
    // reached EOS -- return null
    return null;
  }

这里有对字符大小写的控制。停用词存放在set中,对TokenStream中的Token进行逐一排查。

 

四)中文分词

中文分词目前主要是基于词库的方式,然后做最大匹配。例如IKAnalyzer。

也有基于统计的作法,例如CNSmart(Lucene提供)。

这里面又包括:人名、地名、机构名称的识别,未登录词的识别,歧义消除等内容。

欲知详情,请听下回分解。: P

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值