You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solr基于双字段最小值的自定义排序实现问询

Solr 双字段最小值自定义排序实现方案

1. 实现自定义MinValueSource类

该类负责计算两个字段的最小值,并提供对应的排序字段实现:

import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.SortField;

import java.io.IOException;
import java.util.Map;

public class MinValueSource extends ValueSource {
    private final ValueSource field1;
    private final ValueSource field2;

    public MinValueSource(ValueSource field1, ValueSource field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    @Override
    public FunctionValues getValues(Map context, org.apache.lucene.index.LeafReaderContext readerContext) throws IOException {
        FunctionValues vals1 = field1.getValues(context, readerContext);
        FunctionValues vals2 = field2.getValues(context, readerContext);

        return new DoubleDocValues(this) {
            @Override
            public double doubleVal(int doc) throws IOException {
                double val1 = vals1.doubleVal(doc);
                double val2 = vals2.doubleVal(doc);
                // 处理空值:此处将空值视为无穷大,可根据业务需求调整逻辑
                if (Double.isNaN(val1)) return val2;
                if (Double.isNaN(val2)) return val1;
                return Math.min(val1, val2);
            }
        };
    }

    @Override
    public SortField getSortField(boolean reverse) {
        return new SortField(null, new MinFieldComparatorSource(this), reverse);
    }

    @Override
    public String description() {
        return "customsort(" + field1.description() + ", " + field2.description() + ")";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MinValueSource that = (MinValueSource) o;
        return field1.equals(that.field1) && field2.equals(that.field2);
    }

    @Override
    public int hashCode() {
        int result = field1.hashCode();
        result = 31 * result + field2.hashCode();
        return result;
    }
}

2. 实现自定义ComparatorSource类

为排序逻辑提供自定义比较器:

import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.queries.function.FunctionValues;

import java.io.IOException;
import java.util.Map;

public class MinFieldComparatorSource extends FieldComparatorSource {
    private final MinValueSource minValueSource;

    public MinFieldComparatorSource(MinValueSource minValueSource) {
        this.minValueSource = minValueSource;
    }

    @Override
    public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
        return new FieldComparator.DoubleComparator(numHits, fieldname, false) {
            private FunctionValues values;

            @Override
            public void setNextReader(org.apache.lucene.index.LeafReaderContext context) throws IOException {
                values = minValueSource.getValues(Map.of(), context);
            }

            @Override
            public int compare(int slot1, int slot2) {
                double val1 = values.doubleVal(slot1);
                double val2 = values.doubleVal(slot2);
                return Double.compare(val1, val2);
            }

            @Override
            public int compareBottom(int doc) throws IOException {
                double val1 = values.doubleVal(doc);
                double val2 = bottom;
                return Double.compare(val1, val2);
            }

            @Override
            public void copy(int slot, int doc) throws IOException {
                bottom = values.doubleVal(doc);
            }
        };
    }
}

3. 实现ValueSourceParser解析自定义函数

该类负责将查询中的customsort(field1, field2)语法转换为MinValueSource实例:

import org.apache.lucene.queries.function.ValueSource;
import org.apache.solr.search.FunctionQParser;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.ValueSourceParser;

public class MinValueSourceParser extends ValueSourceParser {
    @Override
    public ValueSource parse(FunctionQParser fp) throws SyntaxError {
        ValueSource field1 = fp.parseValueSource();
        ValueSource field2 = fp.parseValueSource();
        return new MinValueSource(field1, field2);
    }
}

4. 在Solr配置中注册自定义Parser

编辑solrconfig.xml,添加配置让Solr识别自定义函数:

<valueSourceParser name="customsort" class="com.yourpackage.MinValueSourceParser"/>

注意替换com.yourpackage为实际的Java包路径。

5. 使用示例

查询时直接指定sort参数即可:

sort=customsort(field1, field2) asc

对应文档示例:

  • document1: field1=4, field2=6 → 最小值4
  • document2: field1=7, field2=5 → 最小值5
  • document3: field1=2, field2=9 → 最小值2

排序后结果顺序为:document3 → document1 → document2,完全匹配需求。

内容的提问来源于stack exchange,提问作者Ritesh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:05:23