今天继续学习lucene搜索引擎,汤老师讲了compass,它对lucene进行分装,就象hibernate对jdbc进行分装一样,减少了编写的代码量。并使用compass在bbs中加入了对文章的查询功能。还讲了索引的相关度,分词器,高亮器,索引的查询方式。
1,Directory,有两个:
a) FSDirectory,将索引放到磁盘中。
b) RAMDirectory,将索引放到内存中。速度快,但是在jvm退出之后,内存中
的索引就不存在了。可以在jvm退出之前调用另一个使用FSDirectory的
IndexWriter 把内存中的索引转存到文件系统中。
相应的API为IndexWriter.addIndexesNoOptimize(Directory[]),注意这个调
用代码要放在内存中索引的操作RAMDirectory的IndexWriter关闭后,以便所有的
document都进入RAMDirectory。在创建RAMDirectory的实例时,可以使用无参的构
造方法,或是有一个参数的构造方法:可以指定一个文件路径,以便加载磁盘中的索引到内存中。
2,相关度排序,Lucene的搜索结果默认按相关度排序的,所谓相关度,就是文档
的得分。Lucene有一个评分机制,就是对检索结果按某种标准进行评估,然后按
分值的高低来对结果进行排序。
a) 文档的得分与用户输入的关键字有关系,而且是实时运算的结果。得分会受关
键字在文档中出现的位置与次数等的影响。
b) 可以利用Boost影响Lucene查询结果的排序,通过设置Document的Boost来影响
文档的权重,以达到控制查询结果顺序的目的:Document.setBoost(float)。默
认值为1f,值越大,得分越高。
c) 也可以在查询时给Filed指定boost。当同样的term属于不同的field时,如果
field的boost不一样,其所属的文件的得分也不一样。
3,Analyzer,分词器,对文本资源进行切分,将文本按规则切分为一个个可以进
行索引的最小单位(关键字)。
对于英文的分词,是按照标点、空白等拆分单词,比较简单;而中文的分词就比
较复杂了,如”中华人民共和国“可以分为”中华”、“人民”、“共和国”,
但不应有“华人”这个词(不符合语义)。
中文分词几种常用的方式:
a) 单字分词,就是按照中文一个字一个字地进行分词。如:我们是中国人,效果:
我/们/是/中/国/人。(StandardAnalyzer就是这样)。
b) 二分法:按两个字进行切分。如:我们是中国人,效果:我们/们是/是中/中
国/国人。(CJKAnalyzer就是这样)。
c) 词库分词:按某种算法构造词然后去匹配已建好的词库集合,如果匹配到就切
分出来成为词语。通常词库分词被认为是最理想的中文分词算法如:我们是中
国人,通成效果为:我们/是/中国/中国人。对词库的需求太过庞大,并需要实时更新,一般不采用它。
4,Highlighter,高亮器,用于高亮显示匹配的关键字。
包含三个主要部分:
1) 格式化器:Formatter(使用SimpleHTMLFormatter,在构造时指定前缀和后缀)2) 计分器:Scorer(使用QueryScorer)。
3) 段划分器:Fragmenter(使用SimpleFragmenter,在构造时指定关键字所在的
内容片段的长度)。
通过方法getBestFragment(Analyzer a, String fieldName,String text)实现高亮。
(如果进行高亮的field中没有出现关键字,返回null)。
5,查询,有两种方式:通过Query Parser解析查询字符串或使用API构建查询。
使用Query Parser时不匹分大小写。以下是常用的查询:
1) TermQuery,按Term(关键字)查询(term的值应是最终的关键字,英文应全部小写)。
TermQuery(Term t);
syntax: propertyName:keyword;
2) RangeQuery,指定范围查询。
RangeQuery(Term lowerTerm, Term upperTerm, boolean inclusive);
syntax: propertyName:[lower TO upper](包含lower和upper);
syntax: propertyName:{lower TO upper}(不包含lower和upper);
3) PrefixQuery,前缀查询。
PrefixQuery(Term prefix);
syntax:propertyName:prefix*;
4) WildcardQuery,通配符查询,可以使用"?"代表一个字符,"*"代表0个或多个字符。
(通配符不能出现在第一个位置上)
WildcardQuery(Term term);
syntax: propertyName:chars*chars?chars
5) MultiFieldQueryParser,在多个Field中查询。
queryParser = MultiFieldQueryParser(String[] fields, Analyzer analyzer);
Query query = parse(String query);
6) BooleanQuery,布尔查询。这个是一个组合的Query,可以把各种Query添加进
去并标明他们的逻辑关系。
TermQuery q1 = new TermQuery(new Term("title","javadoc"));
TermQuery q2 = new TermQuery(new Term("content","term"));
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add(q1, Occur.MUST);
boolQuery.add(q2, Occur.MUST_NOT);
Occur.MUST,必须出现。
Occur.MUST_NOT,必须未出现。
Occur.SHOULD,只有一个SHOULD时为必须出现,多于一个时为或的关系。
syntax: + - AND NOT OR (必须为大写)。