1、tf = sqrt(phraseFreq)。所以,第一个结果里面的第二个doc的tf = sqrt(1.5)=1.2247。
2、idf = 所有term的idf的和。而一个term的idf = 1 - log((docFreq + 1)/numOfDocs)。也就是说,对于第一个结果来说,idf = 2 * (1 - log(5/4)) = 1.5537。
3、fieldNorm是事先计算好了的,它等于1/sqrt(wordsNum - 1)。比如,文档2的name属性有4个词语,所以,fieldNorm = 1/sqrt(4-1)= 0.57735。可是,Lucene使用8位来表示这个值,所以,会有精度的损失,最后得到的结果是0.5。
TermQuery
TermQuery 最简单(上文提到过), 用Term t=new Term("contents","junit"); new TermQuery(t)就可以构造
TermQuery把查询条件视为一个keyword, 要求和查询内容完全匹配,比如Field.Keyword类型就可以使用TermQuery
RangeQuery
RangeQuery 看名字就知道是表示一个范围的搜索条件,RangeQuery query = new RangeQuery(begin, end, included);
boolean参数表示是否包含边界条件本身, 用字符表示为"[begin TO end]"()包含边界值 或者"{begin TO end}"(不包含边界值)
PrefixQuery
顾名思义,就是表示以XX开头的查询, 字符表示为"something*"
BooleanQuery
逻辑组合的Query,你可以把各种Query添加进去并标明他们的逻辑关系,添加条件用如下方法
public void add(Query query, boolean required, boolean prohibited)
后两个boolean变量是标示AND OR NOT三种关系(如果同时取true的话是不和逻辑的哦 ) 字符表示为" AND OR NOT" 或 "+ -" ,一个BooleanQuery中可以添加多个Query, 如果超过setMaxClauseCount(int)的值(默认1024个)的话,会抛出TooManyClauses错误.
表3:两个参数的组合
|
required |
|||
false |
true |
|||
prohibited |
false |
Clause is optional |
Clause must match |
|
true |
Clause must not |
match |
Invalid |
|
|
|
|
|
|
PhraseQuery
表示不严格语句的查询,比如"quick fox"要匹配"quick brown fox","quick brown high fox"等,PhraseQuery所以提供了一个setSlop()参数,在查询中,lucene会尝试调整单词的距离和位置,这个参数表示可以接受调整次数限制,如果实际的内容可以在这么多步内调整为完全匹配,那么就被视为匹配.在默认情况下slop的值是0, 所以默认是不支持非严格匹配的, 通过设置slop参数(比如"quick fox"匹配"quick brown fox"就需要1个slop来把fox后移动1位),我们可以让lucene来模糊查询. 值得注意的是,PhraseQuery不保证前后单词的次序,在上面的例子中,"fox quick"需要2个slop,也就是如果slop如果大于等于2,那么"fox quick"也会被认为是匹配的.如果是多个Term的搜索,slop指最大的所以的用到次数.看个例子就更明白了:
Lucene系统的排序是根据信息检索的向量空间模型来计算的。文档(d)和查询条件(q)之间越接近,那么文档(d)的得分就越高。计算公司如下:
score(q,d) = coord(q,d) · queryNorm(q) · |
∑ |
( tf(t in d) · idf(t)2 · t.getBoost() · norm(t,d) ) |
|
t in q |
|
其中:
1. tf(t in d)
表示的是查询条件中,每个(t:term)在本文档(d)中的出现频率。查询关键词出现的频率越高,文档的得分就越高。这个部分的默认计算公式是:
frequency½ |
2. idf(t)
表示的是反转文档频率( Inverse Document Frequency).这个函数表示的是(t:term)在所有文档中一共在多少个文档中出现过。因为文档出现的次数越少就越容易定位,所以文档数越少,得分就越高。这个函数的默认计算公式如下:
idf(t) = |
1 + log ( |
|
) |
3.coord(q,d)
这个函数表示的是在这个文档(d)中Term(t)出现的百分比,也就是文档中出现的不同Term数量和查询条件(q)中的不同Term(t)的数量之比。所以,文档中出现的Term种类越多,分值就高。
4.queryNorm(q) 这个函数是一个调节因子,不影响具体的排序情况。主要是用来让排序结果在不同的查询条件(或者不同的索引)之间可以比较。这个条件是在搜索的时候计算的。它的计算公式如下: The sum of squared weights (查询条件的terms)是由查询的权重对象计算的。不同的查询方式,有不同的计算方法。例如:Boolean query的计算公式如下:
queryNorm(q) = queryNorm(sumOfSquaredWeights) = |
|
||||
∑ |
( idf(t) · t.getBoost() ) 2 |
||||
|
t in q |
|
5.norm(t,d)
这个函数得到的是一些建索引的时候得到的一些参数计算值:encapsulates a few (indexing time) boost and length factors:
Document boost – 文档的boost,是建索引的时候设置的文档得分。
o Field boost – 在将一个字段加入到文档中去的时候加入的字段得分。(不同的字段得分不同有利于排序,例如标题的得分应该比内容的得分要高等)
o lengthNorm(field) – 文档在建立索引的时候加入的一个参数,根据文档的某个字段含有的Term数量来计算的。Term数量比较少的字段将得到更多的得分。这个函数是由Similarity类在建立索引的时候计算的。 (1/numTerms*numTerms)
当一片文档加入到索引中去的时候,所有的上面因子将乘起来。如果一个文档含有多个同名的当一个文档有多个字段的名字也叫做这个名字的时候,这些字段的boost值也乘一块儿:
norm(t,d)=doc.getBoost()·lengthNorm(field) · |
∏ |
|
|
field f in d named as t |
|
最 后,norm的结果是经过加密,形成一个单字节的形式保存的。在搜索的时候,这个字节从索引目录中读取,然后解密成float型的norm值。这种压缩/ 解压缩的过程可以减少索引的大小,但是会有一定精度上的损失。也就是说decode(encode(x))并不一定等于x,比如说decode (encode(0.89))=0.75。
架构概览
图一显示了 Lucene 的索引机制的架构。Lucene 使用各种解析器对各种不同类型的文档进行解析。比如对于 HTML 文档,HTML 解析器会做一些预处理的工作,比如过滤文档中的 HTML 标签等等。HTML 解析器的输出的是文本内容,接着 Lucene 的分词器(Analyzer)从文本内容中提取出索引项以及相关信息,比如索引项的出现频率。接着 Lucene 的分词器把这些信息写到索引文件中。
图一:Lucene 索引机制架构
用Lucene索引文档
接下来我将一步一步的来演示如何利用 Lucene 为你的文档创建索引。只要你能将要索引的文件转化成文本格式,Lucene 就能为你的文档建立索引。比如,如果你想为 HTML 文档或者 PDF 文档建立索引,那么首先你就需要从这些文档中提取出文本信息,然后把文本信息交给 Lucene 建立索引。我们接下来的例子用来演示如何利用 Lucene 为后缀名为 txt 的文件建立索引。
1. 准备文本文件
首先把一些以 txt 为后缀名的文本文件放到一个目录中,比如在 Windows 平台上,你可以放到 C://files_to_index 下