当前位置: 首页 > 知识库问答 >
问题:

Lucene6-如何用数值影响排名?

景修杰
2023-03-14
    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();

名称是我们要搜索的字段,总和是我们要对搜索结果进行加权的字段(但仍要考虑与作者名称的最佳匹配)。我不确定在这种情况下,将总和添加到文档中是否是正确的做法。我知道需要一些实验来找出如何最好地混合这两个因素的权重,但我的问题是我不知道如何首先做到这一点。

我能找到的任何例子要么是Lucene4之前的,要么似乎不起作用。我以为这就是我要找的,但似乎不起作用。感谢您的帮助!

共有1个答案

唐修能
2023-03-14

如您链接的博客文章所示,您可以使用CustomScoRequery;这会给你很大的灵活性和对得分过程的影响,但这也有点矫枉过正。另一种可能是使用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);
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);
    }       
}

现在可以使用新的查询类修改现有查询,类似于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方法,所以不要在那里执行任何昂贵的计算,因为这会严重减慢搜索过程。

 类似资料:
  • 我想根据数字字段对搜索结果进行排序。在下面的示例代码中,我希望基于'Age'字段进行排序。我从以下答案开始: [如何在Lucene 6中对IntPont或LongPoint字段进行排序 [在Lucene中根据数字字段对搜索结果进行排序 我在搜索函数中将sortfield.type.score更改为sortfield.type.long。但我得到: 意外的docvalues为字段“年龄”键入NONE

  • 问题内容: 我最近发现,LEFT JOIN的ON子句可能包含诸如(1 = 1)的值。 这让我很沮丧,因为它破坏了我对联接功能的理解。 我遇到了以下情况的详细版本: 这是完全合法的。如果有的话,“ Manager.ID = -1”会完成什么工作?这如何影响Join? 问题答案: 如果人员表是: 如果经理表是 如果查询是: 那么结果是: 在这里,所有人员行都以-1 Admin(在manager表上)联

  • 本文向大家介绍物联网如何影响大数据,包括了物联网如何影响大数据的使用技巧和注意事项,需要的朋友参考一下 当涉及到当今最受关注的两种技术时,大数据和物联网(IoT)可能正处于主导地位。在过去的几年中,大数据在许多领域都取得了进步。尽管物联网恰好与众不同,但它已与大数据紧密相连。 什么是大数据? 大数据本质上是大量复杂形式的数据。具体来说,它还涉及使用预测分析和方法,这些方法和方法可从此类数据中提取有

  • 问题内容: TCP_NODELAY是启用TCP数据包大小大小的快速选项。当速度很重要时,这是一个非常有用的选项,但是,我很好奇它将对此做些什么: 我试图找到冲洗实际上对起作用,但据我所知,它什么也没做。我曾希望它能告诉套接字“立即发送所有缓冲的数据”,但是不幸的是,没有。 我的问题是:这3个字节的数组是否在一个数据包中发送?我知道您对TCP如何构造网络数据包没有太多控制权,但是有什么方法可以告诉套

  • 我有一个非常基本的JavaFX应用程序,如果应用程序类不是主类,它可以完美无缺地工作: 但是,当我将两者合并在一起时(这是大多数教程,包括OpenJFX的官方文档中推荐的方式),模块系统会抛出(至少在OpenJDK 11.0.2上): 例外情况是: java.lang.IllegalAccessError:类(在未命名的模块中)无法访问类(在模块中),因为模块不会将导出到未命名的模块 奇怪的是,我

  • 问题内容: 我想使用BigDecimal来表示任意精度的数字,例如在每秒处理数千个订单和执行报告的低延迟交易应用程序中的价格和金额。 我不会对它们进行很多数学运算,因此问题不关乎BigDecimal本身的性能,而是关乎BigDecimal对象的数量会影响应用程序的性能。 我担心的是,大量短暂的BigDecimal对象会给GC造成压力,并导致CMS收集器中更大的Stop-The-World停顿-这绝