Analyzer(分词器)
分词器能以某种规则对关键字进行分词,将分好的词放到目录中,以作为检索到的条件,在创建索引时会使用到分词器,在搜索时也将用到分词器,这两个地方要使用同一个分词器,否则可能找不到结果.分词器一般的工作流程:
- 切分关键词
- 去除停用词
- 对于英文单词,把所有字母转为小写
注:有的分词器对英文支持的非常好,还能对英文单词进行时态还原.
停用词的概念
有些词在文本中出现的频率非常高,但是对文本所携带的信息基本不产生影响,例如英文的“a、an、the、of”,或中文的“的、了、着”,以及各种标点符号等,这样的词称为停用词(stop word).文本经过分词之后,停用词通常被过滤掉,不会被进行索引.在检索的时候,用户的查询中如果含有停用词,检索系统也会将其过滤掉(因为用户输入的查询字符串也要进行分词处理).排除停用词可以加快建立索引的速度,减小索引库文件的大小
常用的中文分词器
中文的分词比较复杂,因为不是一个字就是一个词,而且一个词在另外一个地方就可能不是一个词,如在"帽子和服装"中,"和服"就不是一个词.对于中文分词,通常有三种方式:
单字分词:就是按照中文一个字一个字地进行分词.如:"我们是中国人",效果:"我"、"们"、"是"、"中"、"国"、"人".(StandardAnalyzer就是这样)
二分法分词:按两个字进行切分.如:"我们是中国人",效果:"我们"、"们是"、"是中"、"中国"、"国人".(CJKAnalyzer就是这样)
词库分词:按某种算法构造词,然后去匹配已建好的词库集合,如果匹配到就切分出来成为词语.通常词库分词被认为是最理想的中文分词算法.如:"我们是中国人",效果为:"我们"、"中国人".(使用极易分词的MMAnalyzer.可以使用极易分词,或者是庖丁分词分词器、IKAnalyzer等).
测试分词器
/**
|
* 使用指定的分词器对指定的文本进行分词,并打印结果
|
* @param analyzer
|
* @param text
|
* @throws Exception
|
*/
|
private void testAnalyzer(Analyzer analyzer, String text) throws Exception { |
System.out.println("当前使用的分词器:" + analyzer.getClass()); |
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text)); |
tokenStream.addAttribute(TermAttribute.class); |
while (tokenStream.incrementToken()) { |
TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class); |
System.out.println(termAttribute.term()); |
} |
} |
|
Highlighter(高亮器)
在搜索结果中经常可以看到,自己搜索的关键字加上了一些效果,以突出显示,Lucene自然提供了这样的设置,我们需要用到Highlighter这个类,用之前需要配置好:
/**
|
* Formatter:设置高亮器的格式,无参构造函数表示使用<b>标签
|
* Scorer:Highlighter需要知道哪些关键词是需要高亮的,需要需要查询条件
|
*/
|
Formatter formatter = new SimpleHTMLFormatter(); |
Scorer scorer = new QueryScorer(query); |
Highlighter highlighter = new Highlighter(formatter,scorer); |
//除了上面两个以外,还需要生成一段摘要,以便搜索的时候显示,指定摘要的大小为20个字符
|
Fragmenter fragmenter = new SimpleFragmenter(20); |
highlighter.setTextFragmenter(fragmenter); |
只需要配置这三样就可以了,接着我们要在每一次获取Field对象数据的时候做一些工作,因为高亮器实际上就是在内容中加了一点样式,我们当然要指定在哪里加:
/**
|
* 在循环获取每一条记录的时候,让高亮器找到需要高亮的关键词,
|
* 要提供相应的分词器和告诉它高亮哪一个Field中的内容
|
* 一次只能高亮一个Field,如需要高亮多个Field,需要写多次
|
* 就像这样:
|
String text1 = highlighter.getBestFragment(
|
Configuration.analyzer, "title",
|
doc.get("title"));
|
*/
|
String text = highlighter.getBestFragment(Configuration.analyzer, "content", doc.get("content")); |
if(text != null){ |
doc.getField("content").setValue(text); |
} |
一定要放在循环里面,highlighter.getBestFragment()方法本身没有副作用,也就是不改变原有的值,返回一个改变后的结果,所以要手动地改变Field中原有的值,并且if的条件最好不要省略,有时候可以会有这样一种情况,出现关键字的位置在其他Field里面,所以如果当前高亮的属性值中没有出现搜索关键字,则返回null.
排序
排序有几种方式,最常用的也就是相关度排序,把最有可能是用户需要的数据放在前面.由高到低排序,默认即是使用相关度排序.当然,我们也可以控制相关度排分的比重,比如我们想让一条记录的得分加倍,就要在建立索引时,加几句操作:
Document doc = DocumentUtils.docConvert(article, Document.class); |
//setBoost()方法需要一个float类型的参数,表示将相关度得分的因子增加多少倍
|
doc.setBoost(2F); |
indexWriter.addDocument(doc); |
这样加进去的索引,就会改变默认的相关度得分因子.如果我们想靠某个Field的值来排序也可以,默认是升序,如果是按某个Field的值来排序,那将不会生成相关度得分,因为没有必要.假设按ID进行升序排列:
Sort sort = new Sort(new SortField("id",SortField.INT)); |
TopDocs topDocs = indexSearcher.search(query,null, 100,sort); |
IndexSearcher的search()方法需要改成接收4个参数的重载方法,第二个参数需要一个Filter,这里不需要,就传入null,Sort需要知道按什么排序,由SortField的第一个构造参数指明,第二参数指明类型,接收一个int值,由SortField对象的常量值表示.还可以加入第三个参数:
Sort sort = new Sort(new SortField("id", SortField.INT, true)); |
表示是否倒序排序.也可以指定多个排序规则.由多个SortField组成第1顺序、第2顺序...
过滤
使用Filter可以对搜索结果进行过滤,以获得更小范围的结果.使用Filter对性能的影响很大(有可能会使查询慢上百倍).假如我要看ID从5到15的:
//第三个参数:是否包含最小值(5);第四个参数:是否包含最大值(15)
|
Filter filter = NumericRangeFilter.newIntRange("id", 5, 15, true,true); |
//这个时候就不需要第四个参数来指定排序了,search()这个方法有很多重载版本
|
TopDocs topDocs = indexSearcher.search(query,filter, 100); |
光这样写还不行,会看不到结果.这是因为要过滤的值,如果是数字,需要以指定的格式存储才行,否则将按字符串的方式来比较.
对于这个问题,需要引出一个工具类:NumericUtils,这个工具类专门做数值与数值或字符串间的转换工作.要在对象到Document以及Document到对象的转换的时候进行,这是对于数值,如果是日期类型,需要使用这个工具类:DateTools.
注:这样做了以后,可能还是不行,对于使用NumericUtils把数字转换为字符串,一定要使用Index.NOT_ANALYZED,以保存能够正确的使用Filter
其他搜索
首先,有两种搜索方式:
- 使用QueryParser(或MultiFieldQueryParser)解析查询字符串的方式
- 自己直接创建Query子类的实例方式
由于可以使用Query对象的toString()方法打印出对应的查询语法,所以以第二种方式做的话,可以看相应的第一种查询方法:
/* 1.匹配所有对应的查询字符串为: *:*
|
Query query = new MatchAllDocsQuery();
|
|
2.范围查询对应的查询字符串为: id:[5 TO 15]
|
Query query = NumericRangeQuery.newIntRange("id", 5, 15, true, true);
|
范围查询对应的查询字符串为: id:{5 TO 15}
|
Query query = NumericRangeQuery.newIntRange("id", 5, 15, false,false);
|
范围查询对应的查询字符串为: id:{5 TO 15]
|
Query query = NumericRangeQuery.newIntRange("id", 5, 15, false, true);
|
|
3.关键词对应的查询字符串为: title:lucene
|
Query query = new TermQuery(new Term("title", "lucene"));
|
|
4.通配符对应的查询字符串为: title:lucen?
|
Query query = new WildcardQuery(new Term("title", "lucen?"));
|
通配符对应的查询字符串为: title:lu*ne
|
Query query = new WildcardQuery(new Term("title", "lu*ne"));
|
|
5.短语对应的查询字符串为: title:"lucene ? ? 工作"
|
PhraseQuery phraseQuery = new PhraseQuery();
|
phraseQuery.add(new Term("title", "lucene"), 0); // 第一个词的索引是0
|
phraseQuery.add(new Term("title", "工作"), 3);
|
短语对应的查询字符串为: title:"lucene 工作"~5
|
phraseQuery.add(new Term("title", "lucene"));
|
phraseQuery.add(new Term("title", "工作"));
|
phraseQuery.setSlop(5); // 指定这些词中间的间隔最多不会超过5个词
|
|
6.布尔查询
|
对应的查询语法两种:
|
1. + 代表MUST,-表示NOT
|
2. AND、OR、NOT,注意要全是大写
|
3. MUST 必须满足
|
MUST_NOT 非
|
SHOULD 多个SHOULD一起用,是OR的关系
|
|
Query query1 = new TermQuery(new Term("title", "lucene"));
|
Query query2 = NumericRangeQuery.newIntRange("id", 5, 15, false, true);
|
对应的查询字符串为: +title:lucene +id:{5 TO 15]
|
对应的查询字符串为: title:lucene AND id:{5 TO 15]
|
booleanQuery.add(query1, Occur.MUST);
|
booleanQuery.add(query2, Occur.MUST);
|
|
对应的查询字符串为: +title:lucene -id:{5 TO 15]
|
对应的查询字符串为: title:lucene NOT id:{5 TO 15]
|
booleanQuery.add(query1, Occur.MUST);
|
booleanQuery.add(query2, Occur.MUST_NOT);
|
|
对应的查询字符串为: title:lucene id:{5 TO 15]
|
对应的查询字符串为: title:lucene OR id:{5 TO 15]
|
booleanQuery.add(query1, Occur.SHOULD);
|
booleanQuery.add(query2, Occur.SHOULD);
|
----------------------------------------------------
|
MUST + SHOULD,与只有一个MUST效果相同
|
SHOULD + MUST_NOT,这时SHOULD就相当MUST
|
MUST_NOT + MUST_NOT,没有匹配结果,也不报错。
|
*/ |
分享到:
相关推荐
来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器。 1. 正向全切分算法,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I 1.6G 1G内存 WinXP) 2. 对数量词、地名、路名的...
2. **配置与初始化**:根据项目需求,配置分词器的参数,如自定义词典、分词模式等,然后在Lucene的Analyzer中实例化该分词器。 3. **索引建立**:在创建索引时,使用配置好的分词器对中文文本进行分词,生成分词后...
ikanalyzer分词器是一款在Java环境下广泛使用的中文分词工具,尤其在搜索引擎和文本分析领域中扮演着重要角色。它的核心是ikanalyzer.jar类库,这个库包含了分词算法和其他必要的支持类,使得开发者能够轻松地集成到...
本文将深入探讨Lucene的核心组件及其与IKAnalyzer分词器的结合使用。 首先,我们来了解一下Lucene的核心组件。`lucene-core-3.6.1.jar`是Lucene的核心库,包含了索引和搜索的主要功能,如文档的添加、删除和更新,...
词典包含了大量已知的词语,分词器会根据词典来识别出连续的字符序列是否为一个完整的词语。词典的大小和质量直接影响了分词的准确性。Lucene允许用户自定义词典,以适应特定领域的分词需求。 2. **模糊匹配和歧义...
IKAnalyzer分词器版本 2012 兼容Lucene3.3以上版本 对solr1.4提供接口实现 使用IK分词器,应为该集群使用到的solr版本为4.10.3-cdh5.7.5,所以使用的 IK 包为IKAnalyzer2012FF_u1.jar,如果是3x的solr,使用IK...
3. **分词器分词**:这是核心步骤,IKAnalyzer采用动态调优算法,能够在运行时根据上下文调整分词策略,以达到更好的分词效果。它支持基于正向最大匹配(MMAX)和逆向最大匹配(RMMAX)等多种分词模式。 4. **歧义...
### Lucene4.0 IK分词器使用概览 #### IKAnalyzer:中文分词利器 IKAnalyzer是一款基于Java开发的开源中文分词工具包,自2006年首次发布以来,历经多个版本的迭代,已成为业界广泛认可的中文分词解决方案。其最初...
2. **配置分词器**:在Lucene.NET的索引创建阶段,需要配置Analyzer类,指定使用特定的分词器。例如,使用IK Analyzer可以创建`IKAnalyzer analyzer = new IKAnalyzer();`。 3. **字段分析**:在创建Document对象时...
**IKAnalyzer分词器** IKAnalyzer是一款开源的、基于Java实现的中文分词器,它在中文信息处理领域有着广泛的应用。这个分词工具最初由尹吉团队开发,旨在为Java开发者提供一个简单易用、性能高效的中文分词库。在...
用java写的图形分词测试的小东西,用的分词器是: 来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器,其使用“正向全切分算法”,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I...
**IKAnalyzer分词器**是Java开发的一款高性能的中文分词工具,主要应用于搜索引擎和文本分析领域。它的设计目标是提供一个轻量级、高效能的解决方案,支持自定义词典,可以方便地集成到各种系统中。在本资源中,我们...
本话题将深入探讨四种常用的Java分词工具:word分词器、ansj分词器、mmseg4j分词器以及ik-analyzer,以及它们在实际应用中的效果评估。 首先,ansj分词器是由李弄潮开发的一款开源分词工具,它具有强大的词典支持和...
在Lucene中,你可以通过创建`Analyzer`实例,然后使用`Document`对象来添加字段,如药品名称和功能主治,这些字段会被分词器处理。 在索引建立完成后,可以使用Lucene提供的搜索API来进行查询。这通常涉及到创建`...
分词器的配置是灵活的,可以根据需求选择不同的分词策略,比如标准分词器(StandardAnalyzer)适用于大多数英文文本,而中文分词可能需要使用IKAnalyzer或SmartChineseAnalyzer等针对中文特性的分词器。 在运行这个...
提示:IKAnalyzer中文分词器支持Lucene6.0以上,IKAnalyzer中文分词器支持Lucene6.0以上。
在Lucene索引构建过程中,你可以将IKAnalyzer作为Analyzer,这样分词器会自动处理文本的分词工作,提升搜索精度。 总之,IKAnalyzer中文分词器以其高效、易用和可扩展性在Java领域的中文处理中占有一席之地。通过...
lucene中文分词器Jceseg和IK Analyzer使用示例,lucene5可以使用,本人亲测成功,大家放心用,喜欢lucene的人大家关注我的博客 http://blog.csdn.net/wuyinggui10000/article/category/3173543 大家共同交流,有需要...
IKAnalyzer是一个开源的,基于Java语言开发的轻量级的中文分词语言包,它是以Lucene为应用主体,结合词典分词和文法分析算法的中文词组组件。从3.0版本开始,IK发展为面向java的公用分词组件,独立Lucene项目,同时...
6. **Lucene接口集成**:为了让C#分词器与Lucene接口兼容,需要理解并实现Lucene的分析器(Analyzer)接口,以便于在索引和查询过程中正确处理中文文本。 7. **性能优化**:在实际应用中,分词速度和资源占用是重要...