【问题标题】:Add weights to documents Lucene 8为文档添加权重 Lucene 8
【发布时间】:2019-11-04 21:23:33
【问题描述】:

我目前正在开发一个使用 Lucene 8 的小型大学搜索引擎。我之前已经构建了它,但没有对文档应用任何权重。

我现在需要添加文档的 PageRanks 作为每个文档的权重,并且我已经计算了 PageRank 值。如何在 Lucene 8 中为 Document 对象(不是查询词)添加权重?我在网上查找了许多解决方案,但它们仅适用于旧版本的 Lucene。 Example source

这是我的(更新)代码,它从File 对象生成Document 对象:

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;

}

我当前方法的问题是我需要一个 CustomScoreQuery 对象来搜索文档,但这在 Lucene 8 中不可用。此外,我不想在所有代码之后现在降级到 Lucene 7我用 Lucene 8 写的。


编辑:

经过一些(长时间的)研究,我在每个包含 boost 的文档中添加了一个 DoubleDocValuesField(请参阅上面的更新代码),并按照 @EricLavault 的建议使用 FunctionScoreQuery 进行搜索。但是,现在我的所有文档的得分都与其提升完全一致,无论查询如何!我该如何解决这个问题?这是我的搜索功能:

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;
    }
}

【问题讨论】:

标签: java lucene


【解决方案1】:

关于我编辑的问题(提升值完全取代搜索分数而不是提升它),这是documentationFunctionScoreQuery 所说的(强调我的):

包装另一个查询的查询,并使用 DoubleValuesSource 来替换或修改包装查询的分数。

那么,什么时候替换,什么时候修改呢?

原来,我使用的代码是用提升值完全替换分数:

Query q = new FunctionScoreQuery(q_temp, DoubleValuesSource.fromDoubleField("boost")); //the new query

我需要做的是使用函数boostByValue,它修改搜索分数(通过将分数乘以提升值):

Query q = FunctionScoreQuery.boostByValue(q_temp, DoubleValuesSource.fromDoubleField("boost"));

现在它可以工作了!感谢@EricLavault 的帮助!

【讨论】:

    【解决方案2】:

    Lucene 6.5.0开始:

    不推荐使用索引时间提升。作为替代品, 索引时间评分因素应该被索引到一个文档值字段中 并在查询时使用例如组合。函数评分查询。 (阿德里安 大)

    建议将评分因素(即长度标准化因素)编码到文档值字段中,而不是使用索引时间提升。 (参见LUCENE-6819

    【讨论】:

    • 我尝试这样做,但到目前为止没有取得多大成功。问题已更新详细信息。如果您能提供帮助,我将不胜感激!
    • 我终于设法解决了我的问题。不过感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多