《Lucene in Action 第二版》第4章节 学习总结 -- Lucene中的分析
通过第四章的学习,可以了解lucene的分析过程是怎样的,并且可以学会如何使用lucene内置分析器,以及自定义分析器。下面是具体总结
1. 分析(Analysis)是什么?
在lucene中,分析就是指:将域(Field)文本转换成最基本的索引表示单元---项(Term)的过程。而项(Term)又是由语汇单元(Token)以及它所属的域名组合而成的。
在索引过程中存在分析(IndexWriter的初始化中需要放入一个Analyzer的实例;并且如果要使Analyzer生效,则需要使用Index.ANALYZED或者Index.ANALYZED_NO_NORMS属性);在利用QueryParser进行搜索的过程中也存在分析(QueryParser的初始化中也需要放入一个Analyzer的实例)。
分析是通过分析器(Analyzer)进行的。Lucene推荐,在索引和搜索期间,使用相同的Analyzer进行处理。
分析器不能做什么?分析器的前提是域已经分好了。因此必须在使用分析器之前,先把文本预先解析并形成域。分析器内不可以创建新的域。
2. Analyzer的作用,就是分析输入的字符文件。其主要的过程如下:
通过调用某个具体Analyzer子类的TokenStream(String fieldName, Reader reader)(reader里面就包含了输入的要解析的文本,fieldname可以为空,即"";但是在不为空时,它起到什么作用呢?),将输入的文本分析成Term。而在TokenStream内部,则可以:1.首先用一个具体的Tokennzer对象从输入的文本创建初始语汇单元序列;2.然后用任意数量(可以是0个)的tokenFilter对象来修改这些语汇单元。最终产生的就是语汇单元流:TokenStream。
3. 语汇单元流是由各个语汇单元组成的。而每个语汇单元的组成,包括了:文本值本身+其他一些元数据。这些都可以理解为该语汇单元的属性,它们是可以通过具体对象实例的API方法得到的。具体为:
TermAttribute ---- 语汇单元对应的文本,通过 .term()方法就可以得到具体文本值
PositionIncrementAttribute --- 本语汇单元相对于前一个语汇单元的位置增量(默认值是1)。通过. getPositionIncrement()可以得到位置增量的值。
OffsetAttriute --- 语汇单元的起始字符和终止字符的偏移量。其中起始字符偏移量表示的是语汇单元的文本的起始字符在原始文本中的位置,通过.startOffset()得到;而终止字符偏移量则表示语汇单元的文本终止字符的下一个位置。通过.endOffset()得到
TypeAttribute --- 语汇单元类型(默认是 word)。通过.type()得到。
FlagsAttribute --- 自定义标志位 (具体怎么用,尚不清楚)
PayloadAttribute --- 每个语汇单元的byte[]类型有效负载(具体怎么用,尚不清楚)
4. Lucene的内置分析器是需要熟练掌握和运用的。而且书上说,适用范围最广的分析器是StandardAnalyzer
5. 如何创建自己的分析器:一般构建自定义分析器,需要定义Analyzer子类以及自定义TokenFilter;而Tokenizer一般是用现成的。常规套路如下:
A. 自定义一个Analyzer,继承自Analyzer,即书上的例子:
public class MetaphoneReplacementAnalyzer extends Analyzer {
@Override
public TokenStream tokenStream(String fieldName, Reader reader) {
// TODO Auto-generated method stub
returnnew MetaphoneReplacementFilter(new LetterTokenizer(reader));
}
}
B. 自定义TokenFilter(可以是一个或者多个)。在自定义的TokenFilter中,一般就要利用语汇单元的各种属性来对语汇单元进行过滤了。并且还要实现在TokenFilter中唯一要实现的方法:incrementToken()
public class MetaphoneReplacementFilter extends TokenFilter {
public static final String METAPHONE = "metaphone";
private Metaphone metaphoner = new Metaphone();
private TermAttribute termAttr;
private TypeAttribute typeAttr;
protected MetaphoneReplacementFilter(TokenStream input) {
super(input);
// TODO Auto-generated constructor stub
termAttr = addAttribute(TermAttribute.class);
typeAttr = addAttribute(TypeAttribute.class);
}
@Override
public boolean incrementToken() throws IOException {
// TODO Auto-generated method stub
if(!input.incrementToken()) {
return false;
}
String encoded;
encoded = metaphoner.encode(termAttr.term());
termAttr.setTermBuffer(encoded);
typeAttr.setType(METAPHONE);
return true;
}
}
6. 同时,要知道:网络上有很多现成的分析器实现,可以借用的
7. 好东西:PerFieldAnalyzerWrapper
经常的,我们会遇到这样的索引:一个Doc中有多个Field,每个Field中存储的值是不一样的。比如:一个域:partnum,存储的值是"Q36",存储的方式是Store,但是NOTANALYZED(也就是要求将Q36作为一个整体进行索引);另一个域:description,存储的值是"Illidium Space Modulator"",存储的方式是Store,同时是ANALYZED。然后,我们需要利用QueryParser来针对字符串"partnum:Q36 AND SPACE"进行搜索。
这时,就会遇到一个问题:用哪种Analyzer呢?因为QueryParser的构造函数中,只能放入一个Analyzer,而这里,partnum域是NOTANALYZED,而description域是ANALYZED。似乎Lucene自带的Analyzer是无法同时满足这两个域的搜索要求的。那么,这里的PerFieldAnalyzerWrapper就可以帮忙了。它可以在默认Analyzer的基础上,针对特定域可以绑定一个特定的Analyzer。然后,我们将PerFiledAnalyzerWrapper所创建的这个“混合”分析器,放入QueryParser的构造方法中就可以了。具体例子代码如下:
PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(new SimpleAnalyzer()); //先构建一个PerFieldAnalyzerWrapper实例,放入缺省的分析器
analyzer.addAnalyzer("partnum", new KeywordAnalyzer()); //给特定Field绑定特定Analyzer
Query query = new QueryParser(Version.LUCENE_30, "description", analyzer).parse("partnum:Q36 AND SPACE"); //这里就要采用PerFieldAnalyzerWrapper分析器了
《Lucene in Action 第二版》第4章节 学习总结 -- Lucene中的分析的更多相关文章
- 《Lucene in Action第二版》学习总结---如何在Windows下编译luceneinAction2Edition源码包
1. 下载此源码包,位置是: www.manning.com/hatcher3,得到:lia2e.tar.gz,然后解压缩得到目录:lia2e,为了以后能辨识,我将此目录改名为:luceneinAct ...
- 《Lucene in Action 第二版》第三章节的学习总结----IndexSearcher以及Term和QueryParser
本章节告诉我们怎么用搜索.通过这章节的学习,虽然搜索的内部原理不清楚,但是至少应该学会简单的编写搜索程序了本章节,需要掌握如下几个主要API1.IndexSearcher类:搜索索引的门户,发起者. ...
- 《Lucene in Action》(第二版) 第一章节的学习总结 ---- 用最少的代码创建索引和搜索
第一章节是介绍性质,但是通过这一章节的学习,我理解到如下概念: 1.Lucene由两部分组成:索引和搜索.索引是通过对原始数据的解析,形成索引的过程:而搜索则是针对用户输入的查找要求,从索引中找到匹配 ...
- lucene实战(第二版)学习笔记
初识Lucene 构建索引 为应用程序添加搜索功能 Lucene的分析过程
- 《TomCat与Java Web开发技术详解》(第二版) 第一章节的学习总结--HTTP组成+基本访问方式
1.需要看懂HTML文件中的组成元素的基本含义.不同的组成元素,可以使得HTML支持文本,图片(img,将图片发给客户端),静态音频/视频(embed src,将音频视频发给客户端),超链接(href ...
- 采用WPF开发第二版OFD阅读器,持续完善中,敬请期待!
本人研究OFD多年,采用C#和QT开发了一系列ofd相关软件.在这些产品中,阅读器始终占据着非常重要的位置.可以说,阅读器是直接面向最终客户的产品.是集OFD各类知识之大成的产品.市面上的阅读器产品林 ...
- 《selenium2 Java 自动化测试实战(第二版)》 更新2016.5.3
java 版来了!! 本文档在<selenium2 Python 自动化测试实战>的基础上,将代码与实例替换为java ,当然,部分章节有变更.这主要更语言本身的特点有关.集合和java下 ...
- 简单的web三层架构系统【第二版】
昨天写了 web三层架构的第一版,准确的说是三层架构的前期,顶多算是个二层架构,要慢慢完善. 第一版里,程序虽说能运行起来,但是有一个缺陷,就是里面的SQL语句,是使用的拼接字符进行执行.这样安全系数 ...
- Lucene.net站内搜索—6、站内搜索第二版
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
随机推荐
- HttpWebRequest 请求 Api 及 异常处理
HttpWebRequest request = WebRequest.CreateHttp(url); request.Method = "post"; request.Head ...
- SQLite中的内连接简化技巧
SQLite中的内连接简化技巧 在SQLite中,通过内连接可以将两个表通过条件表达式关联起来,构成一个新记录集或视图.形式如下: SELECT ... FROM t1 JOIN t2 ON ...
- bmi健康指数
#!/usr/bin/python # -*- coding: utf-8 -*- #小明身高1.75,体重80.5kg.请根据BMI公式(体重除以身高的平方) #帮小明计算他的BMI指数,并根据BM ...
- luogu P1091 合唱队形
题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2, ...
- linux-配置字符串-grep
grep -rn "hello,world!" * * : 表示当前目录所有文件,也可以是某个文件名 -r 是递归查找 -n 是显示行号 -R 查找所有文件包含子目录 -i 忽略大 ...
- JSON-JSON 百科
1,百度百科 http://baike.baidu.com/view/136475.htm?fr=aladdin 2,JSON教程 http://www.w3school.com.cn/json/
- 分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace
Bus Hound官方下载地址:http://perisoft.net/bushound/Bus Hound 简易使用手册:bus_hound5.0中文使用说明.pdf (246 K) 下载次数:9 ...
- 配置php扩展memcache
配置php扩展memcache 环境说明: 系统版本 CentOS 6.9 x86_64 软件版本 nginx-1.12.2 php-5.5.38 ...
- Angular 学习笔记——ng-disable
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <met ...
- 1通过URL对象的openStream()方法能够得到指定资源的输入流。
通过URL读取网页内容 1通过URL对象的openStream()方法能够得到指定资源的输入流. 2通过输入流能够读取.訪问网络上的数据. 案例: import java.io ...