文档章节

lucene自定义分词器

Zero零_度
 Zero零_度
发布于 2015/08/08 16:47
字数 794
阅读 1279
收藏 4

工作上,有需要对纯数字的字符串做分词,好像CJK二元分词器对这样的数字不会做分词,所以自己写了个分词器,分词器达到以下效果:对字符串1234567,分词后为:12 34 56 7

Analyzer:

package org.apache.lucene.analysis.core;
import java.io.Reader;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.util.CharTokenizer;
import org.apache.lucene.util.Version;

public final class MyNumberAnalyzer extends Analyzer {
  
  public MyNumberAnalyzer() {}
   
  @Deprecated
  public MyNumberAnalyzer(Version matchVersion) {
    setVersion(matchVersion);
  }
  
  @Override
  protected TokenStreamComponents createComponents(final String fieldName,
      final Reader reader) {
    return new TokenStreamComponents(new MyNumberTokenizer(getVersion(), reader));
  }
  
  public static void main(String[] args) throws Exception {   
   MyNumberAnalyzer analyzer = new MyNumberAnalyzer();
   //WhitespaceAnalyzer analyzer = new WhitespaceAnalyzer();
   TokenStream tokenStream = analyzer.tokenStream("content", new StringReader("123467899988"));
   tokenStream.reset();
   tokenStream.addAttribute(CharTermAttribute.class);
   while(tokenStream.incrementToken()){
    CharTermAttribute termAttribute = tokenStream.getAttribute(CharTermAttribute.class);
   System.out.println(termAttribute.toString());
   }
  }
}

Tokenizer:

package org.apache.lucene.analysis.core;

import java.io.Reader;

import org.apache.lucene.analysis.util.MyCharTokenizer;
import org.apache.lucene.util.AttributeFactory;
import org.apache.lucene.util.Version;

public final class MyNumberTokenizer extends MyCharTokenizer {
 
 private long count = 0;
 
  public MyNumberTokenizer(Reader in) {
    super(in);
  }

  @Deprecated
  public MyNumberTokenizer(Version matchVersion, Reader in) {
    super(matchVersion, in);
  }

  public MyNumberTokenizer(AttributeFactory factory, Reader in) {
    super(factory, in);
  }

  @Deprecated
  public MyNumberTokenizer(Version matchVersion, AttributeFactory factory, Reader in) {
    super(matchVersion, factory, in);
  }
 
  @Override
  protected boolean isTokenChar(int c) {
   return get();
  }
 
  public synchronized boolean get() {
   count++;
   if(count%2 == 0) {
    count = 0L;
    return false;
   }
   return true;
  }

}

Tokenizer:

package org.apache.lucene.analysis.util;
import java.io.IOException;
import java.io.Reader;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.util.CharTokenizer;
import org.apache.lucene.analysis.util.CharacterUtils;
import org.apache.lucene.analysis.util.CharacterUtils.CharacterBuffer;
import org.apache.lucene.util.AttributeFactory;
import org.apache.lucene.util.Version;
public abstract class MyCharTokenizer extends Tokenizer {
  
  public MyCharTokenizer(Reader input) {
    super(input);
    charUtils = CharacterUtils.getInstance();
  }
  @Deprecated
  public MyCharTokenizer(Version matchVersion, Reader input) {
    super(input);
    charUtils = CharacterUtils.getInstance(matchVersion);
  }
  
  public MyCharTokenizer(AttributeFactory factory, Reader input) {
    super(factory, input);
    charUtils = CharacterUtils.getInstance();
  }
  @Deprecated
  public MyCharTokenizer(Version matchVersion, AttributeFactory factory,
      Reader input) {
    super(factory, input);
    charUtils = CharacterUtils.getInstance(matchVersion);
  }
  private int offset = 0, bufferIndex = 0, dataLen = 0, finalOffset = 0;
  private static final int MAX_WORD_LEN = 255;
  private static final int IO_BUFFER_SIZE = 4096;
  
  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
  private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
  
  private final CharacterUtils charUtils;
  private final CharacterBuffer ioBuffer = CharacterUtils.newCharacterBuffer(IO_BUFFER_SIZE);
  
 
  protected abstract boolean isTokenChar(int c);
  protected int normalize(int c) {
    return c;
  }
@Override
public final boolean incrementToken() throws IOException {
    clearAttributes();
    int length = 0;
    int start = -1; // this variable is always initialized
    int end = -1;
    char[] buffer = termAtt.buffer();
    while (true) {
     //第一次进入,bufferIndex=dataLen=0
     if (bufferIndex >= dataLen) {
      offset += dataLen;//offset=0
      
      //将数据拷贝进入ioBuffer
      charUtils.fill(ioBuffer, input); // read supplementary char aware with CharacterUtils
      
      //
      if (ioBuffer.getLength() == 0) {
       dataLen = 0; // so next offset += dataLen won't decrement offset
       if (length > 0) {
        break;
       } else {
        finalOffset = correctOffset(offset);
        //返回false,表示分词结束
        return false;
       }
      }
      
      //重置数据的长度
      dataLen = ioBuffer.getLength();
      
      //重置起始位置
      bufferIndex = 0;
     }
     
     // use CharacterUtils here to support < 3.1 UTF-16 code unit behavior if the char based methods are gone
     //取得ioBuffer中第bufferIndex位的字符
     final int c = charUtils.codePointAt(ioBuffer.getBuffer(), bufferIndex, ioBuffer.getLength());
     //获得字符长度
     final int charCount = Character.charCount(c);
     
     //起始位置加charCount
     bufferIndex += charCount;
     //
     if(isTokenChar(c)) {               // if it's a token char
      if (length == 0) {                // start of token
       assert start == -1;
       start = offset + bufferIndex - charCount;
       end = start;
      } else if (length >= buffer.length-1) { // check if a supplementary could run out of bounds
       buffer = termAtt.resizeBuffer(2+length); // make sure a supplementary fits in the buffer
      }
      end += charCount;
      length += Character.toChars(normalize(c), buffer, length); // buffer it, normalized
      if (length >= MAX_WORD_LEN) { // buffer overflow! make sure to check for >= surrogate pair could break == test
       break;
      }
     } else if (length > 0) {             // at non-Letter w/ chars
      //length++;
      //end++;
      
      if (length == 0) {                // start of token
       assert start == -1;
       start = offset + bufferIndex - charCount;
       end = start;
      } else if (length >= buffer.length-1) { // check if a supplementary could run out of bounds
       buffer = termAtt.resizeBuffer(2+length); // make sure a supplementary fits in the buffer
      }
      end += charCount;
      length += Character.toChars(normalize(c), buffer, length); // buffer it, normalized
      if (length >= MAX_WORD_LEN) { // buffer overflow! make sure to check for >= surrogate pair could break == test
       break;
      }
      
      break;                           // return 'em
     }
    }
    termAtt.setLength(length);
    assert start != -1;
    offsetAtt.setOffset(correctOffset(start), finalOffset = correctOffset(end));
    return true;
}
  
  @Override
  public final void end() throws IOException {
    super.end();
    // set final offset
    offsetAtt.setOffset(finalOffset, finalOffset);
  }
  @Override
  public void reset() throws IOException {
    super.reset();
    bufferIndex = 0;
    offset = 0;
    dataLen = 0;
    finalOffset = 0;
    ioBuffer.reset(); // make sure to reset the IO buffer!!
  }
}

TokenizerFactory:

package org.apache.lucene.analysis.core;
import java.io.Reader;
import java.util.Map;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.util.AttributeFactory;
public class MyNumberTokenizerFactory extends TokenizerFactory {
  public MyNumberTokenizerFactory(Map<String,String> args) {
    super(args);
    if (!args.isEmpty()) {
      throw new IllegalArgumentException("Unknown parameters: " + args);
    }
  }
  @Override
  public MyNumberTokenizer create(AttributeFactory factory, Reader input) {
    if (luceneMatchVersion == null) {
      return new MyNumberTokenizer(factory, input);
    }
    return new MyNumberTokenizer(luceneMatchVersion, factory, input);
  }
}

© 著作权归作者所有

Zero零_度
粉丝 69
博文 1267
码字总数 263854
作品 0
程序员
私信 提问
lucene4.7 分词器(三)

前面几章笔者把Lucene基本入门的任督二脉给打通了,从此篇开始,就开始进行Lucene的进阶开发了,那么首先摆在我们面前的第一个必须要解决的问题,就是关于中文分词的问题,因为Lucene毕竟是国...

一枚Sir
2014/04/10
1K
0
solr添加中文IK分词器,以及配置自定义词库

Solr是一个基于Lucene的Java搜索引擎服务器。Solr 提供了层面搜索、命中醒目显示并且支持多种输出格式(包括 XML/XSLT 和 JSON 格式)。它易于安装和配置,而且附带了一个基于HTTP 的管理界面...

超人学院
2015/05/08
7.1K
0
[Elasticsearch] 索引管理 (二)

自定义解析器(Custom Analyzers) 虽然ES本身已经提供了一些解析器,但是通过组合字符过滤器(Character Filter),分词器(Tokenizer)以及词条过滤器(Token Filter)来创建你自己的解析器才会显示...

键走偏锋
2017/08/02
40
0
从Lucene到Elasticsearch:Lucene 开发入门

https://gitee.com/jly521/lucene-demo.git Lucene :开源的全文检索引擎工具包 优点:: Lucene 架构图:: 检索分4步:: 查询分析 搜索通常全开放 纠错 分词技术 关键词检索 搜索排序 Lu...

Java搬砖工程师
01/03
51
0
Lucene4.3开发之第四步之脱胎换骨(四)

前面几章把lucene基本入门的任督二脉给打通了,从此篇开始,就开始进行lucene的进阶开发了,那么首先摆在我们前面的第一个必须要解决的问题,就是关于中文分词的问题,因为lucene毕竟是国外大...

heroShane
2014/02/21
261
1

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— 当你简历注水但还是找到了工作

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享成龙的单曲《男儿当自强》。 《男儿当自强》- 成龙 手机党少年们想听歌,请使劲儿戳(这里) @hxg2016 :刚在...

小小编辑
今天
2.9K
22
靠写代码赚钱的一些门路

作者 @mezod 译者 @josephchang10 如今,通过自己的代码去赚钱变得越来越简单,不过对很多人来说依然还是很难,因为他们不知道有哪些门路。 今天给大家分享一个精彩的 GitHub 库,这个库整理...

高级农民工
昨天
5
0
用好项目管理工具,人人都可以成为项目经理

现在市面上的项目管理工具越来越多了,但是大多数都是一些协同工具或轻量项目管理工具。如果是多团队、跨部门使用或者企业级的项目管理,从管理思想到工具运用,需要适应企业的业务流程体系,...

cs平台
昨天
12
0
只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
69
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部