1、score(q,d) = coord(q,d) queryNorm(q) ( tf(t in d) idf(t)2 t.getBoost() norm(t,d) ) t in qDocument Boost和Field Boost影响的是norm(t, d),其公式如下:norm(t,d) doc.getBoost() lengthNorm(field) f.getBoost() field f in d named as t它包括三个参数: Document boost:此值越大,说明此文档越重要。 Field boost:此域越大,说明此域越重要。 lengthNorm(field) =
2、(1.0 / Math.sqrt(numTerms):一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。其中第三个参数可以在自己的Similarity中影响打分,下面会论述。当然,也可以在添加Field的时候,设置Field.Index.ANALYZED_NO_NORMS或Field.Index.NOT_ANALYZED_NO_NORMS,完全不用norm,来节约空间。根据Lucene的注释,No norms means that index-time field and document boosting and field length normalization
3、 are disabled. The benefit is less memory usage as norms take up one byte of RAM per indexed field for every document in the index, during searching. Note that once you index a given field with norms enabled, disabling norms will have no effect. 没有norms意味着索引阶段禁用了文档boost和域的boost及长度标准化。好处在于节省内存,不用在搜索阶
4、段为索引中的每篇文档的每个域都占用一个字节来保存norms信息了。但是对norms信息的禁用是必须全部域都禁用的,一旦有一个域不禁用,则其他禁用的域也会存放默认的norms值。因为为了加快norms的搜索速度,Lucene是根据文档号乘以每篇文档的norms信息所占用的大小来计算偏移量的,中间少一篇文档,偏移量将无法计算。也即norms信息要么都保存,要么都不保存。下面几个试验可以验证norms信息的作用:试验一:Document Boost的作用public void testNormsDocBoost() throws Exception File indexDir = new File(
5、testNormsDocBoost); IndexWriter writer = new IndexWriter(FSDirectory.open(indexDir), new StandardAnalyzer(Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); writer.setUseCompoundFile(false); Document doc1 = new Document(); Field f1 = new Field(common hello hello doc1.add(f1); doc1.s
6、etBoost(100); writer.addDocument(doc1); Document doc2 = new Document(); Field f2 = new Field(common common hello, Field.Store.NO, Field.Index.ANALYZED_NO_NORMS); doc2.add(f2); writer.addDocument(doc2); Document doc3 = new Document(); Field f3 = new Field(common common common doc3.add(f3); writer.add
7、Document(doc3); writer.close(); IndexReader reader = IndexReader.open(FSDirectory.open(indexDir); IndexSearcher searcher = new IndexSearcher(reader); TopDocs docs = searcher.search(new TermQuery(new Term(common), 10); for (ScoreDoc doc : docs.scoreDocs) System.out.println(docid : + doc.doc + score :
8、 + doc.score); 如果第一篇文档的域f1也为Field.Index.ANALYZED_NO_NORMS的时候,搜索排名如下: 2 score : 1.2337708 1 score : 1.0073696 0 score : 0.71231794如果第一篇文档的域f1设为Field.Index.ANALYZED,则搜索排名如下: 39.889805 0.6168854 0.5036848试验二:Field Boost的作用如果我们觉得title要比contents要重要,可以做一下设定。public void testNormsFieldBoost() throws Excepti
9、on testNormsFieldBoosttitle f1.setBoost(100); QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, , new StandardAnalyzer(Version.LUCENE_CURRENT); Query query = parser.parse(title:common contents: TopDocs docs = searcher.search(query, 10); 0.49999997 0.35355338 19.79899 0.49999997试验三:norms中文
10、档长度对打分的影响public void testNormsLength() throws Exception testNormsLengthcommon common hello hello hello hello当norms被禁用的时候,包含两个common的第二篇文档打分较高: 0.13928263 0.09848769当norms起作用的时候,虽然包含两个common的第二篇文档,由于长度较长,因而打分较低: 0.09848769 0.052230984试验四:norms信息要么都保存,要么都不保存的特性public void testOmitNorms() throws Except
11、ion testOmitNorms for (int i = 0; i 10000; i+) 当我们添加10001篇文档,所有的文档都设为Field.Index.ANALYZED_NO_NORMS的时候,我们看索引文件,发现.nrm文件只有1K,也即其中除了保持一定的格式信息,并无其他数据。当我们把第一篇文档设为Field.Index.ANALYZED,而其他10000篇文档都设为Field.Index.ANALYZED_NO_NORMS的时候,发现.nrm文件又10K,也即所有的文档都存储了norms信息,而非只有第一篇文档。在搜索语句中,设置Query Boost.在搜索中,我们可以指定,
12、某些词对我们来说更重要,我们可以设置这个词的boost:common4 hello使得包含common的文档比包含hello的文档获得更高的分数。由于在Lucene中,一个Term定义为Field:Term,则也可以影响不同域的打分:common4 content:common使得title中包含common的文档比content中包含common的文档获得更高的分数。实例:public void testQueryBoost() throws Exception TestQueryBoostcommon1 hello hellocommon2 common2 hellocommon1 com
13、mon2根据tf/idf,包含两个common2的第二篇文档打分较高: 0.24999999 0.17677669如果我们输入的查询语句为:common1100 common2,则第一篇文档打分较高: 0.2499875 0.0035353568那Query Boost是如何影响文档打分的呢?根据Lucene的打分计算公式:注:在queryNorm的部分,也有q.getBoost()的部分,但是对query向量的归一化(见向量空间模型与Lucene的打分机制继承并实现自己的SimilaritySimilariy是计算Lucene打分的最主要的类,实现其中的很多借口可以干预打分的过程。(1) f
14、loat computeNorm(String field, FieldInvertState state)(2) float lengthNorm(String fieldName, int numTokens)(3) float queryNorm(float sumOfSquaredWeights)(4) float tf(float freq)(5) float idf(int docFreq, int numDocs)(6) float coord(int overlap, int maxOverlap)(7) float scorePayload(int docId, String fieldName, int start, int end, byte payload, int offset, int length)它们分别影响Lucene打分计算的如下部分: (6)coord(q,d) (3)queryNorm(q) ( (4)tf(t in d) (5)idf(t)2 (1)norm(t,d) )t in q (2)lengthNorm(field) field f in d
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1