同义词功能在全文搜索时的意义,大家应该都懂的。今天中文我就试着写了一个同义词分词的示例demo,其实主要代码还是参考Lucene in Action 这本英文版书籍的随书代码,只不过Lucenen in Action书里的示例代码目前最新版只支持到Lucene4.x,对于Lucene5.x,代码需要稍作修改,下面是基于Lucene5.x的自定义同义词分词器demo:
package com.yida.framework.lucene5.analyzer.synonym; import java.io.IOException; /** * 同义词提取引擎 * @author Lanxiaowei * */ public interface SynonymEngine { String[] getSynonyms(String s) throws IOException; }
package com.yida.framework.lucene5.analyzer.synonym; import java.io.IOException; import java.util.HashMap; public class BaseSynonymEngine implements SynonymEngine { private static HashMap<String, String[]> map = new HashMap<String, String[]>(); { map.put("quick", new String[] {"fast","speedy"}); map.put("jumps", new String[] {"leaps","hops"}); map.put("over", new String[] {"above"}); map.put("lazy", new String[] {"apathetic","slugish"}); map.put("dog", new String[] {"canine","pooch"}); } public String[] getSynonyms(String s) throws IOException { return map.get(s); } }
package com.yida.framework.lucene5.analyzer.synonym; import java.io.IOException; import java.util.Stack; import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.util.AttributeSource; /** * 自定义同义词过滤器 * * @author Lanxiaowei * */ public class SynonymFilter extends TokenFilter { public static final String TOKEN_TYPE_SYNONYM = "SYNONYM"; private Stack<String> synonymStack; private SynonymEngine engine; private AttributeSource.State current; private final CharTermAttribute termAtt; private final PositionIncrementAttribute posIncrAtt; public SynonymFilter(TokenStream in, SynonymEngine engine) { super(in); synonymStack = new Stack<String>(); // #1 this.engine = engine; this.termAtt = addAttribute(CharTermAttribute.class); this.posIncrAtt = addAttribute(PositionIncrementAttribute.class); } public boolean incrementToken() throws IOException { if (synonymStack.size() > 0) { // #2 String syn = synonymStack.pop(); // #2 restoreState(current); // #2 // 这里Lucene4.x的写法 // termAtt.setTermBuffer(syn); // 这是Lucene5.x的写法 termAtt.copyBuffer(syn.toCharArray(), 0, syn.length()); posIncrAtt.setPositionIncrement(0); // #3 return true; } if (!input.incrementToken()) // #4 return false; if (addAliasesToStack()) { // #5 current = captureState(); // #6 } return true; // #7 } private boolean addAliasesToStack() throws IOException { // 这里Lucene4.x的写法 // String[] synonyms = engine.getSynonyms(termAtt.term()); //#8 // 这里Lucene5.x的写法 String[] synonyms = engine.getSynonyms(termAtt.toString()); // #8 if (synonyms == null) { return false; } for (String synonym : synonyms) { // #9 synonymStack.push(synonym); } return true; } } /* #1 Define synonym buffer #2 Pop buffered synonyms #3 Set position increment to 0 #4 Read next token #5 Push synonyms onto stack #6 Save current token #7 Return current token #8 Retrieve synonyms #9 Push synonyms onto stack */
package com.yida.framework.lucene5.analyzer.synonym; import java.io.BufferedReader; 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.Tokenizer; import org.apache.lucene.analysis.Analyzer.TokenStreamComponents; import org.apache.lucene.analysis.core.LetterTokenizer; import org.apache.lucene.analysis.core.LowerCaseFilter; import org.apache.lucene.analysis.core.StopAnalyzer; import org.apache.lucene.analysis.core.StopFilter; import org.apache.lucene.analysis.standard.StandardFilter; import org.apache.lucene.analysis.standard.StandardTokenizer; import com.yida.framework.lucene5.util.analyzer.codec.MetaphoneReplacementFilter; /** * 自定义同义词分词器 * * @author Lanxiaowei * @createTime 2015-03-31 10:15:23 */ public class SynonymAnalyzer extends Analyzer { private SynonymEngine engine; public SynonymAnalyzer(SynonymEngine engine) { this.engine = engine; } @Override protected TokenStreamComponents createComponents(String text) { Tokenizer tokenizer = new StandardTokenizer(); TokenStream tokenStream = new SynonymFilter(tokenizer, engine); tokenStream = new LowerCaseFilter(tokenStream); tokenStream = new StopFilter(tokenStream,StopAnalyzer.ENGLISH_STOP_WORDS_SET); return new TokenStreamComponents(tokenizer, tokenStream); } }
package com.yida.framework.lucene5.analyzer.synonym; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import com.yida.framework.lucene5.util.AnalyzerUtils; public class SynonymAnalyzerTest { public static void main(String[] args) throws IOException { String text = "The quick brown fox jumps over the lazy dog"; Analyzer analyzer = new SynonymAnalyzer(new BaseSynonymEngine()); AnalyzerUtils.displayTokens(analyzer, text); } }
package com.yida.framework.lucene5.util; import java.io.IOException; import junit.framework.Assert; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.analysis.tokenattributes.TypeAttribute; /** * 用于分词器测试的一个简单工具类(用于打印分词情况,包括Term的起始位置和结束位置(即所谓的偏 * 移量),位置增量,Term字符串,Term字符串类型(字符串/阿拉伯数字之类的)) * @author Lanxiaowei * */ public class AnalyzerUtils { public static void displayTokens(Analyzer analyzer,String text) throws IOException { TokenStream tokenStream = analyzer.tokenStream("text", text); displayTokens(tokenStream); } public static void displayTokens(TokenStream tokenStream) throws IOException { OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class); PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class); tokenStream.reset(); int position = 0; while (tokenStream.incrementToken()) { int increment = positionIncrementAttribute.getPositionIncrement(); if(increment > 0) { position = position + increment; System.out.print(position + ":"); } int startOffset = offsetAttribute.startOffset(); int endOffset = offsetAttribute.endOffset(); String term = charTermAttribute.toString(); System.out.println("[" + term + "]" + ":(" + startOffset + "-->" + endOffset + "):" + typeAttribute.type()); } } /** * 断言分词结果 * @param analyzer * @param text 源字符串 * @param expecteds 期望分词后结果 * @throws IOException */ public static void assertAnalyzerTo(Analyzer analyzer,String text,String[] expecteds) throws IOException { TokenStream tokenStream = analyzer.tokenStream("text", text); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); for(String expected : expecteds) { Assert.assertTrue(tokenStream.incrementToken()); Assert.assertEquals(expected, charTermAttribute.toString()); } Assert.assertFalse(tokenStream.incrementToken()); tokenStream.close(); } }
以上代码都是Lucene in Action这本书里面的示例代码,我只不过是基于Lucene5.x把它重写并调试成功了,特此分享,希望对正在学习Lucene5的童鞋们有所帮助。demo代码我会在底下附件里上传,有需要demo源码的请自己在底下的附件里下载,Lucene in Action这本书的随书源码我已上传到我的百度网盘,也一并分享给大家,Lucene in Action随书源码百度网盘下载地址:
千言万语都在代码中,就不多说了,打完收工!
如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,
或者加裙
一起交流学习!
相关推荐
例如,以下是一个简单的示例代码片段,展示了如何构建一个同义词分析器: ```java public class SynonymAnalyzer extends Analyzer { private WordList wordList; public SynonymAnalyzer(Reader reader) throws...
在实际项目中,开发者可以根据业务需求进一步优化搜索算法,提升用户体验,比如添加同义词处理、模糊匹配、拼音搜索等功能。总的来说,盘古分词与Lucene的结合使用,为.NET开发者提供了一套强大的文本处理和搜索工具...
### Elasticsearch 安装 IK 分词器详解 #### 一、背景及需求分析 Elasticsearch 是一款基于 Lucene 的搜索引擎,广泛应用于日志处理、全文检索等场景。它提供了多种内置分词器来处理文本数据,但在实际应用过程中...
这只是一个简单的例子,实际上`TokenFilter`可以实现更复杂的功能,如词形还原、同义词替换等。 在提供的源代码中,你可能看到了更多关于如何实际应用`TokenFilter`的例子,包括如何组合多个`TokenFilter`以及如何...
在查询时,除了相同的分词及过滤过程外,还会额外使用SynonymFilterFactory来处理同义词。 #### 五、Solr安装与配置 - **下载与安装**: - **下载地址**:官方下载地址为http://lucene.apache.org/solr/。 - **...
- 这些文件通常包括但不限于`stopwords.txt`(停用词列表)、`synonyms.txt`(同义词列表)等。 3. **配置schema.xml**: - 在`schema.xml`文件中,配置`text_general`字段类型时,应使用IKAnalyzer作为分析器。 ...
在描述中提到,这个版本的IK Analyzer已经支持同义词、停用词和扩展词,这意味着它可以识别并处理这些词汇的不同形式,从而提供更丰富的搜索结果。 **同义词支持** 同义词功能在信息检索中至关重要,因为用户可能会...
同时,随着自然语言处理技术的发展,Lucene也在不断演进,支持更智能的搜索体验,例如模糊搜索、近似搜索、同义词搜索等。 总之,Lucene作为一款强大的全文检索工具,其学习和应用价值不言而喻。通过深入理解其核心...
- **分析器**:深入讲解了Lucene中的分析器组件,包括分词器、过滤器等,以及如何定制化分析流程以满足特定需求。 - **高级分析技巧**:介绍了如何通过组合不同的分析器来提高搜索质量,例如去除停用词、进行词干...
【标题】"lucene检索新闻数据演示...学习和实践这个示例,可以深入理解Lucene的工作原理,提高全文检索的技能,同时对网页数据的处理和分析也有一定帮助。这在信息检索、大数据分析、内容推荐等领域有着广泛的应用。
例如,标题可能需要更严格的分析,而正文可能允许更多的同义词。 3. **分词与分析**: 分词器将文本分解为单独的词语,然后分析器进一步处理这些词语,去除停用词、进行词形还原等,以提高搜索效果。 4. **索引构建...
- **扩展性**:允许开发者自定义分词器、过滤器和查询解析器,以适应特定业务需求。 5. **优化与性能** - **内存管理**:3.6.2版本对内存使用进行了优化,降低了对系统资源的需求。 - **查询性能**:通过查询...
在提供的代码示例中,可以看到创建了一个`ExtractDigest`类,该类使用了ThesaurusAnalyzer,这是一个扩展的Analyzer,可能包含了对同义词或其他词汇关系的处理。`createIndex`方法用于建立索引,`analyzer`对象负责...
同时,对查询语句进行预处理,如关键词过滤、同义词扩展等,可以有效提高查询性能。 ### 4. 封装示例代码 ```java public class IndexManager { public void addDocument(Document doc) {...} public void ...
索引过程包括分词(Tokenization)、词干提取(Stemming)、同义词处理(Synonym Handling)以及创建倒排索引(Inverted Index)等步骤。 2. **文档(Documents)**: 在 Lucene 中,文档是一个逻辑单元,包含一组...
- **全文检索**:Lucene的核心功能是实现对文本数据的全文检索,即不仅根据关键字匹配,还能识别同义词、近义词等。 - **索引**:Lucene通过建立倒排索引,实现了快速的查询性能。倒排索引将文档中的每个词映射到...
作者详细解释了如何处理停用词、同义词,以及如何利用正则表达式和自定义规则进行文本预处理。 搜索功能是Lucene的核心,书中详述了如何构建查询、执行高级查询语法、实现排序和过滤。此外,还涵盖了相关性调整、...
- **简单示例**:通过构建一个简单的索引和搜索应用程序,让读者能够快速上手并体验Lucene的强大功能。 **2. 构建搜索索引** - **字段类型**:详细解释了Lucene中的各种字段类型,如存储字段(Stored Fields)、索引...
在实际应用中,分词查询XML可能会结合数据库系统,例如使用Lucene、Elasticsearch等全文搜索引擎,或者自定义实现。这些系统不仅支持XML数据的索引和查询,还提供丰富的查询语法和性能优化手段。 标签“源码”和...