我想计算通过Lucene找到的各种文档的字段COMBINED_FIELD中的每个术语的TF-IDF分数,这些分数由字段规范标准化。正如您在下面的代码中所看到的,我能够在文档的字段中获取每个术语的术语频率,我也可以获得文档频率,但我找不到一种方法来获得此规范查询时的字段。到目前为止,我发现的所有方法都依赖于仅存在于较旧的Lucene版本中的方法,但不适用于Lucene 6.方法可能是使用LeafReader,但我没有找到方法得到它的实例。
您是否知道如何为每个文档获取字段COMBINED_FIELD的规范?
或者我可以使用termVector.size()作为字段长度的替换吗? size()是否考虑了数量 每个术语的出现或每个术语只计算一次?
提前致谢!
IndexSearcher iSearcher = null;
ScoreDoc[] docs = null;
try {
iSearcher = this.searchManager.acquire();
IndexReader reader = iSearcher.getIndexReader();
MultiFieldQueryParser parser = new MultiFieldQueryParser(this.getSearchFields(), this.queryAnalyzer);
parser.setDefaultOperator(QueryParser.Operator.OR);
Query query = parser.parse(QueryParser.escape(searchString));
docs = iSearcher.search(query, maxSearchResultNumber).scoreDocs;
for(int i=0; i < docs.length; i++) {
Terms termVector = reader.getTermVector(docs[i].doc, COMBINED_FIELD);
TermsEnum itr = termVector.iterator();
BytesRef term = null;
PostingsEnum postings = null;
while((term = itr.next()) != null){
String termText = term.utf8ToString();
postings = itr.postings(postings, PostingsEnum.FREQS);
postings.nextDoc();
int tf = postings.freq();
int docFreq = reader.docFreq(new Term(COMBINED_FIELD, term));
//HERE I WANT TO GET THE FIELD LENGTH OF THE CURRENT DOCUMENT
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
this.searchManager.release(iSearcher);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
或者,有没有办法直接从Lucene获取字段的每个术语的TF-IDF或BM25值?
答案 0 :(得分:1)
Lucene在方法org.apache.lucene.search.similarities.Similarity#computeNorm
中编制索引期间的规范,然后对其进行编码并将其存储在.nvm
文件的磁盘上。之后,在查询/评分期间,它仅被解码。
我认为,在Lucene中以编程方式执行此操作的一种可能方法是扩展Similarity类,并在索引和某处存储时以某种方式获取此信息。对我来说听起来不是最好的方式,但至少是一些东西。
另一方面,BM25Similarity
以这种方式计算长度:
discountOverlaps ? state.getLength() - state.getNumOverlap() : state.getLength();
其中getLength()
是字段中的字词数,您可以通过在while
中迭代来计算,就像在示例中一样。