----------------------------------------------------------
lucene的分词_中文分词介绍
----------------------------------------------------------
Paoding:庖丁解牛分词器。已经没有更新了
mmseg:使用搜狗的词库
1.导入包(有两个包:1.带dic的,2.不带dic的)
如果使用不带dic的,得自己指定词库位置
2.创建MMSegAnalyzer(指明词库所在的位置)
----------------------------------------------------------
lucene的分词_实现自定义同义词分词器_思路分析(analyzer---->TokenStream ---> TokenFilter --->Tokenizer)与得到分词器详细信息的构造顺序相反/*
* 实现自定义中文同义词分词器(mmseg词库)
*/
public class MySameAnalyzer extends Analyzer {
@Override
public TokenStream tokenStream(String fieldName, Reader read) {
Dictionary dic = Dictionary
.getInstance("F:\\BaiduYunDownload\\Cache\\lucune\\chinesedic");
return new MySameTokenFilter(new MMSegTokenizer(new MaxWordSeg(dic), read));
}
}
---------------------------------------------------------
lucene的分词_实现自定义同义词分词器_实现分词器
---------------------------------------------------------
Reader ---->MMSegTokenizer(进行分词)---->(添加同义词)MySameTokenFilter(自定义分词器)---->获取同义词(在相同的位置存储同义词)
--->发现同义词--->保存当前状态--->跳到下一个元素--->根据同义词列表来存储元素--->还原状态--->在同一位置保存元素
/*
* 自定义同义词分词过滤器
*/
public class MySameTokenFilter extends TokenFilter {
// 存储分词数据
private CharTermAttribute cta = null;
// 存储语汇单元的位置信息
private PositionIncrementAttribute pia = null;
// 添加是否有同义词的判断变量属性,保存当前元素的状态信息
private AttributeSource.State current;
// 栈存储
private Stack sames = null;
protected MySameTokenFilter(TokenStream input) {
super(input);
cta = this.addAttribute(CharTermAttribute.class);
pia = this.addAttribute(PositionIncrementAttribute.class);
sames = new Stack();
}
@Override
public boolean incrementToken() throws IOException {
// 保存上一个语汇的同义词
while (sames.size() > 0) {
// 出栈,并获取同义词
String str = sames.pop();
// 还原上一个语汇的状态
restoreState(current);
// 在上一个语汇上保存元素
cta.setEmpty();
cta.append(str);
// 设置同义词位置为0
pia.setPositionIncrement(0);
return true;
}
// 跳到下个cta
if (!this.input.incrementToken())
// 没有元素返回false
return false;
if (getSameWords(cta.toString())) {
// 如果有同义词,改变词汇的current状态信息,把当前状态保存(捕获当前状态)
current = captureState();
}
return true;
}
/*
*
* 获取同义词
*/
private Boolean getSameWords(String name) {
Map maps = new HashMap();
maps.put("我", new String[] { "俺", "咱" });
maps.put("湖南", new String[] { "鱼米之乡", "湘" });
String[] sws = maps.get(name);
if (sws != null) {
// 添加进栈中
for (String str : sws) {
sames.push(str);
}
return true;
}
return false;
}
}
----------------------------------------------------
lucene的分词_实现自定义同义词分词器_实现分词器(良好设计方案)
----------------------------------------------------
思路:针对接口编程才是王道
1.创建管理同义词的接口
/*
* 用于存储同义词的接口
*/
public interface MySameContxt {
//获取同义词String[]
public String[] getSameWords(String name);
}
public class MySimpleSameContxt implements MySameContxt {
/*
* 实现同义词接口
*/
Map maps = new HashMap();
public MySimpleSameContxt() {
maps.put("我", new String[] { "俺", "咱" });
maps.put("湖南", new String[] { "鱼米之乡", "湘" });
}
public String[] getSameWords(String name) {
return maps.get(name);
}
}
全代码
/*
* 自定义同义词分词过滤器
*/
public class MySameTokenFilter extends TokenFilter {
// 存储分词数据
private CharTermAttribute cta = null;
// 存储语汇单元的位置信息
private PositionIncrementAttribute pia = null;
// 添加是否有同义词的判断变量属性,保存当前元素的状态信息
private AttributeSource.State current;
// 栈存储
private Stack sames = null;
// 获取专门管理同义词的库
private MySameContxt sameContxt;
protected MySameTokenFilter(TokenStream input, MySameContxt sameContxt) {
super(input);
cta = this.addAttribute(CharTermAttribute.class);
pia = this.addAttribute(PositionIncrementAttribute.class);
sames = new Stack();
this.sameContxt = sameContxt;
}
@Override
public boolean incrementToken() throws IOException {
// 保存上一个语汇的同义词
while (sames.size() > 0) {
// 出栈,并获取同义词
String str = sames.pop();
// 还原上一个语汇的状态
restoreState(current);
// 在上一个语汇上保存元素
cta.setEmpty();
cta.append(str);
// 设置同义词位置为0
pia.setPositionIncrement(0);
return true;
}
// 跳到下个cta
if (!this.input.incrementToken())
// 没有元素返回false
return false;
if (getSameWords(cta.toString())) {
// 如果有同义词,改变词汇的current状态信息,把当前状态保存(捕获当前状态)
current = captureState();
}
return true;
}
/*
*
* 获取同义词
*/
private Boolean getSameWords(String name) {
// 通过接口sameContxt获取同义词的所有String[]
String[] sws = sameContxt.getSameWords(name);
if (sws != null) {
// 添加进栈中
for (String str : sws) {
sames.push(str);
}
return true;
}
return false;
}
}
4.实现TokenStream
/*
* 实现自定义中文同义词分词器(mmseg词库)
*/
public class MySameAnalyzer extends Analyzer {
// 添加同义词词库
private MySameContxt sameContxt;
public MySameAnalyzer(MySameContxt msc) {
this.sameContxt = msc;
}
@Override
public TokenStream tokenStream(String fieldName, Reader read) {
// z最后传递的是自定义的同义词库管理类
Dictionary dic = Dictionary
.getInstance("F:\\BaiduYunDownload\\Cache\\lucune\\chinesedic");
return new MySameTokenFilter(new MMSegTokenizer(new MaxWordSeg(dic),
read), sameContxt);
}
}
public void test05() {
try {
//将同义词词库作为分词器Analyzer的属性获取TokenStream
Analyzer a1 = new MySameAnalyzer(new MySimpleSameContxt());
String txt = "我来自湖南邵阳";
// 创建索引
Directory dir = new RAMDirectory();
IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
Version.LUCENE_35, a1));
Document doc = new Document();
doc.add(new Field("content", txt, Field.Store.YES,
Field.Index.ANALYZED));
writer.addDocument(doc);
writer.close();
// 创建搜索
IndexReader reader = IndexReader.open(dir);
IndexSearcher search = new IndexSearcher(reader);
TopDocs tds = search.search(new TermQuery(new Term("content",
"鱼米之乡")), 10);
for (ScoreDoc sdc : tds.scoreDocs) {
Document docc = search.doc(sdc.doc);
System.out.println(docc.get("content"));
}
// new AnalyzerUtils().displayToken(txt, a1);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}