[英]Add weights to documents Lucene 8
我目前正在使用Lucene 8为大学开发一个小型搜索引擎。 我之前已经构建了它,但没有对文档应用任何权重。
我现在需要添加文档的 PageRanks 作为每个文档的权重,并且我已经计算了 PageRank 值。 如何在 Lucene 8 中为Document
object(非查询词)添加权重? 我在网上查找了许多解决方案,但它们仅适用于旧版本的 Lucene。 示例源
这是我的(更新的)代码,它从File
object 生成Document
object:
public static Document getDocument(File f) throws FileNotFoundException, IOException {
Document d = new Document();
//adding a field
FieldType contentType = new FieldType();
contentType.setStored(true);
contentType.setTokenized(true);
contentType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
contentType.setStoreTermVectors(true);
String fileContents = String.join(" ", Files.readAllLines(f.toPath(), StandardCharsets.UTF_8));
d.add(new Field("content", fileContents, contentType));
//adding other fields, then...
//the boost coefficient (updated):
double coef = 1.0 + ranks.get(path);
d.add(new DoubleDocValuesField("boost", coef));
return d;
}
The issue with my current approach is that I would need a CustomScoreQuery
object to search the documents, but this is not available in Lucene 8. Also, I don't want to downgrade now to Lucene 7 after all the code I wrote in Lucene 8 .
编辑:
经过一些(冗长的)研究,我在每个包含提升的文档中添加了一个DoubleDocValuesField
(请参阅上面的更新代码),并按照@EricLavault 的建议使用FunctionScoreQuery
进行搜索。 然而,现在我所有的文档都得到了完全提升的分数,不管查询如何! 我该如何解决? 这是我搜索的 function:
public static TopDocs search(String query, IndexSearcher searcher, String outputFile) {
try {
Query q_temp = buildQuery(query); //the original query, was working fine alone
Query q = new FunctionScoreQuery(q_temp, DoubleValuesSource.fromDoubleField("boost")); //the new query
q = q.rewrite(DirectoryReader.open(bm25IndexDir));
TopDocs results = searcher.search(q, 10);
ScoreDoc[] filterScoreDosArray = results.scoreDocs;
for (int i = 0; i < filterScoreDosArray.length; ++i) {
int docId = filterScoreDosArray[i].doc;
Document d = searcher.doc(docId);
//here, when printing, I see that the document's score is the same as its "boost" value. WHY??
System.out.println((i + 1) + ". " + d.get("path")+" Score: "+ filterScoreDosArray[i].score);
}
return results;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
//function that builds the query, working fine
public static Query buildQuery(String query) {
try {
PhraseQuery.Builder builder = new PhraseQuery.Builder();
TokenStream tokenStream = new EnglishAnalyzer().tokenStream("content", query);
tokenStream.reset();
while (tokenStream.incrementToken()) {
CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
builder.add(new Term("content", charTermAttribute.toString()));
}
tokenStream.end(); tokenStream.close();
builder.setSlop(1000);
PhraseQuery q = builder.build();
return q;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
从Lucene 6.5.0开始:
不推荐使用索引时间提升。 作为替代,索引时间评分因素应该被索引到一个文档值字段中,并在查询时使用例如。 函数评分查询。 (阿德里安·格兰德)
建议不要使用索引时间提升,而是将评分因子(即长度归一化因子)编码到文档值字段中。 (参见LUCENE-6819 )
关于我编辑的问题(提升值完全取代搜索分数而不是提升它),以下是文档中关于FunctionScoreQuery
的内容(强调我的):
包装另一个查询的查询,并使用 DoubleValuesSource替换或修改包装查询的分数。
那么,什么时候替换,什么时候修改呢?
事实证明,我使用的代码是用提升值完全替换分数:
Query q = new FunctionScoreQuery(q_temp, DoubleValuesSource.fromDoubleField("boost")); //the new query
我需要做的是使用 function boostByValue
来修改搜索分数(通过将分数乘以提升值):
Query q = FunctionScoreQuery.boostByValue(q_temp, DoubleValuesSource.fromDoubleField("boost"));
现在它起作用了! 感谢@EricLavault 的帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.