gpt4 book ai didi

java - Lucene 6 - 如何影响数值排名?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:11:48 27 4
gpt4 key购买 nike

我是 Lucene 的新手,对于任何不清楚的措辞,我深表歉意。我正在开发一个作者搜索引擎。搜索查询是作者姓名。默认搜索结果很好——它们返回最匹配的名称。然而,我们也想按作者受欢迎程度对结果进行排名,这是默认相似度和代表其标题发行量的数值的混合。默认结果的问题是它返回的作者没有人感兴趣,虽然我可以单独按发行量排名,但排名靠前的结果通常与名字不太匹配。几天来我一直在寻找解决方案。

这就是我构建索引的方式:

    IndexWriter writer = new IndexWriter(FSDirectory.open(Paths.get(INDEX_LOCATION)),
new IndexWriterConfig(new StandardAnalyzer()));
writer.deleteAll();
for (Contributor contributor : contributors) {
Document doc = new Document();
doc.add(new TextField("name", contributor.getName(), Field.Store.YES));
doc.add(new StoredField("contribId", contributor.getContribId()));
doc.add(new NumericDocValuesField("sum", sum));
writer.addDocument(doc);
}
writer.close();

名称是我们要搜索的字段,总和是我们要对搜索结果进行加权的字段(但仍要考虑与作者姓名的最佳匹配)。我不确定在这种情况下将总和添加到文档中是否正确。我知道需要进行一些实验才能弄清楚如何最好地混合这两个因素的权重,但我的问题是我一开始就不知道该怎么做。

我能找到的所有示例要么是 Lucene 4 之前的示例,要么似乎不起作用。我以为this是我一直在寻找的东西,但它似乎不起作用。帮助表示赞赏!

最佳答案

如您链接的博客文章中所示,您可以使用 CustomScoreQuery;这会给你很大的灵 active 和对评分过程的影响,但它也有点矫枉过正。另一种可能性是使用 FunctionScoreQuery;由于它们的行为不同,我将对两者进行解释。

使用 FunctionScoreQuery

FunctionScoreQuery 可以修改基于字段的分数。

假设您创建的搜索通常是这样的:

Query q = .... // pass the user input to the QueryParser or similar
TopDocs hits = searcher.search(query, 10); // Get 10 results

然后你可以像这样修改中间的查询:

Query q = .....

// Note that a Float field would work better.
DoubleValuesSource boostByField = DoubleValuesSource.fromLongField("sum");

// Create a query, based on the old query and the boost
FunctionScoreQuery modifiedQuery = new FunctionScoreQuery(q, boostByField);

// Search as usual
TopDocs hits = searcher.search(query, 10);

这将根据字段的值修改查询。然而,遗憾的是,没有可能控制 DoubleValuesSource 的影响(除了在索引期间缩放值)——至少我不知道。

要获得更多控制权,请考虑使用 CustomScoreQuery

使用 CustomScoreQuery

使用这种查询将允许您以任何您喜欢的方式修改每个结果的分数。在这种情况下,我们将使用它来根据索引中的字段更改分数。首先,您必须在索引期间存储您的值(value):

doc.add(new StoredField("sum", sum)); 

然后我们必须创建我们自己的查询类:

private static class MyScoreQuery extends CustomScoreQuery {
public MyScoreQuery(Query subQuery) {
super(subQuery);
}

// The CustomScoreProvider is what actually alters the score
private class MyScoreProvider extends CustomScoreProvider {

private LeafReader reader;
private Set<String> fieldsToLoad;

public MyScoreProvider(LeafReaderContext context) {
super(context);
reader = context.reader();

// We create a HashSet which contains the name of the field
// which we need. This allows us to retrieve the document
// with only this field loaded, which is a lot faster.
fieldsToLoad = new HashSet<>();
fieldsToLoad.add("sum");
}

@Override
public float customScore(int doc_id, float currentScore, float valSrcScore) throws IOException {
// Get the result document from the index
Document doc = reader.document(doc_id, fieldsToLoad);

// Get boost value from index
IndexableField field = doc.getField("sum");
Number number = field.numericValue();

// This is just an example on how to alter the current score
// based on the value of "sum". You will have to experiment
// here.
float influence = 0.01f;
float boost = number.floatValue() * influence;

// Return the new score for this result, based on the
// original lucene score.
return currentScore + boost;
}
}

// Make sure that our CustomScoreProvider is being used.
@Override
public CustomScoreProvider getCustomScoreProvider(LeafReaderContext context) {
return new MyScoreProvider(context);
}
}

现在您可以使用新的 Query 类来修改现有查询,类似于 FunctionScoreQuery:

Query q = .....

// Create a query, based on the old query and the boost
MyScoreQuery modifiedQuery = new MyScoreQuery(q);

// Search as usual
TopDocs hits = searcher.search(query, 10);

最后的评论

使用 CustomScoreQuery,您可以通过各种方式影响评分过程。但是请记住,方法 customScore 会为每个搜索结果调用 - 所以不要在那里执行任何昂贵的计算,因为这会严重减慢搜索过程。

我在这里创建了 CustomScoreQuery 的完整工作示例的小要点:https://gist.github.com/philippludwig/14e0d9b527a6522511ae79823adef73a

关于java - Lucene 6 - 如何影响数值排名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43477166/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com