自定义BM25Similarity类时Solr文档分数不更新问题
问题现象
自定义BM25Similarity类调试Solr分数时,首次编译计算后同一查询的文档分数不再变化,但响应的explain部分显示分数计算逻辑正确;score函数中constant从QueryParser的SolrParam获取,日志显示constant提取及返回的分数值均正常,但最终响应的文档分数未体现最新计算结果。
排查与解决步骤
检查Similarity实例的缓存机制
Solr默认会缓存Similarity实例,一旦初始化完成后不会重新创建。如果constant是在Similarity的构造方法或初始化阶段获取的,后续请求不会重新读取参数,导致constant值固定,分数不再变化。
解决方式:不要在Similarity初始化阶段获取constant,改为在score方法内部每次请求时动态从当前请求上下文获取SolrParam参数;若依赖重启生效则灵活性不足,不推荐。修正constant参数的动态获取逻辑
如果constant是在QueryParser阶段获取后传递给Similarity,但Similarity实例被缓存,后续请求的新constant无法覆盖旧值。
示例修改代码:
@Override public float score(float freq, long encodedNorm) { // 从当前请求上下文动态获取参数 SolrQueryRequest request = SolrQueryRequest.getRequest(); float constant = Float.parseFloat(request.getParams().get("your_constant_param")); float normInverse = cache[((byte) encodedNorm) & 0xFF]; freq = Math.min(freq, maxTf); return (weight - weight / (1f + freq * normInverse)) * constant; }
注:需确保score方法能正确获取请求上下文,可通过ThreadLocal或Solr提供的上下文工具类传递。
验证查询缓存的影响
Solr的Query Cache会缓存查询结果(包括文档分数),后续相同查询直接返回缓存结果,不会重新计算分数。
解决方式:临时在请求参数中添加cache=false关闭缓存测试;或在solrconfig.xml中针对该自定义查询配置禁用缓存,也可通过代码调用setCache(false)方法禁用。检查weight值的缓存情况
如果weight值是在初始化阶段计算并缓存的,即使constant变化,最终分数也可能因weight固定而无变化。
解决方式:确保weight值随请求动态计算,或在constant变化时触发weight的重新计算。
内容的提问来源于stack exchange,提问作者Utkarsh Singh

