记录一次solr自定义函数编写及使用的过程

简介: solr基本查询已经可以满足大多数查询场景,不过作为一款成熟的搜索引擎solr也可以支持编写自定义函数udf并在查询中使用以应对各种复杂的查询场景。

背景:目前我们solr中存储的数据因为很多属性字段的不确定性,选择将数据在一个大字段中合并。如下格式中attr字段代表着一个不确定的属性字段,可能为身高、体重、性别等,也可能为页码、出版方、售价等

{

“id”:“1”

“attr”:“180,80,男”

“type”:“person”

},

{

“id”:“2”

“attr”:“50,人民出版社,50¥”

“type”:“book”

}

针对这种近期产品提出一个要针对人类按照身高排序,书籍类按照售价排序。这种需求怎么搞呢?身高属性已经跟其他属性混为一个字段,常规排序怕是行不通。

思路:既然常规思路行不通,我们想能不能通过函数截取的方式通过比对该字符串指定位置来实现排序呢?下面直接上代码

代码:首先需要定义两个类SubStrValueSourceParser

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.FunctionQParser;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.ValueSourceParser;
public class SubStrValueSourceParser extends ValueSourceParser {
    public SubStrValueSourceParser() {
        super();
    }
    @Override
    public ValueSource parse(FunctionQParser fp) throws SyntaxError {
        String fieldStr = fp.parseArg();//第一个参数
        String bgnLocation = fp.parseArg();//第二个参数数组下标
        ValueSource location = getValueSource(fp, fieldStr);//取得函数调用时指定字段值
//将参数及需要的文档的值传给自定义的ValueSource方法,打分规则在自定义的ValueSource中定制
        SubStrValueSource stringFieldSource = new SubStrValueSource(location, bgnLocation);
        return stringFieldSource;
    }
//该方法是根据字段名,从FunctionQParser得到文档该字段的相关信息
    public ValueSource getValueSource(FunctionQParser fp, String arg) {
        if (arg == null)
            return null;
        SchemaField f = fp.getReq().getSchema().getField(arg);
        return f.getType().getValueSource(f, fp);
    }
}
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.index.LeafReaderContext;
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.queries.function.docvalues.FloatDocValues;
import org.apache.lucene.queries.function.docvalues.IntDocValues;
import org.apache.lucene.queries.function.docvalues.StrDocValues;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class SubStrValueSource extends ValueSource {
    private ValueSource attr13;//需要进行格式转换的字段
    private String location;
    //通过构造方法获取字段
    public SubStrValueSource(ValueSource attr13, String location) {
        this.attr13 = attr13;
        this.location = location;
    }
    @Override
    public FunctionValues getValues(Map map, LeafReaderContext leafReaderContext) throws IOException {
        final FunctionValues fieldValues = attr13.getValues(map,
                leafReaderContext);//获取attr13的值
        return new DoubleDocValues(this) {
            @Override
            public double doubleVal(int i) throws IOException {
                String fieldStr = null;
                Double retValue = 0.00;
                //若要被转化的值为空或者为空字符串则返回0
                if (fieldValues.strVal(i) == null || "".equals(fieldValues.strVal(i))) {
                } else {
                    fieldStr = fieldValues.strVal(i);
                    String[] vList = fieldStr.split(",");
                    //若实际数组长度小于下标则不处理直接返回0,若大于或等于下标则截取对应位置数据
                    if (vList.length < Integer.parseInt(location) + 1) {
                    } else {
                        String content = vList[Integer.parseInt(location)];
                        retValue = Double.parseDouble(content);
                    }
                }
                return retValue;
            }
        };
    }
    @Override
    public boolean equals(Object o) {
        return true;
    }
    @Override
    public int hashCode() {
        return 0;
    }
    @Override
    public String description() {
        return name();
    }
    public String name() {
        return "subStr";
    }
}

发布:代码逻辑编写完毕后打成jar包并按照如下步骤操作

  1. 在solr安装目录下dist目录中将打好的jar包放进去
  2. 在solrconfig.xml中新增以下配置

<lib dir="${solr.install.dir:../../../..}/dist/" regex="com.tl.solr.*\.jar" />

<valueSourceParser name="subStr"

                       class="SubStrValueSourceParser" />

搞定之后重启服务生效

使用效果:

1646278833(1).png

1646278927(1).png


相关文章
|
2月前
|
SQL 搜索推荐 Java
Hive中的UDF是什么?请解释其作用和使用方法。
Hive中的UDF是什么?请解释其作用和使用方法。
57 0
|
2月前
|
SQL 存储 分布式计算
Hive的性能优化有哪些方法?请举例说明。
Hive的性能优化有哪些方法?请举例说明。
93 0
|
2月前
|
SQL 数据采集 Java
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
51 0
|
2月前
|
Oracle Java 关系型数据库
Generator【SpringBoot集成】代码生成+knife4j接口文档(2种模板设置、逻辑删除、字段填充 含代码粘贴可用)保姆级教程(注意事项+建表SQL+代码生成类封装+测试类)
Generator【SpringBoot集成】代码生成+knife4j接口文档(2种模板设置、逻辑删除、字段填充 含代码粘贴可用)保姆级教程(注意事项+建表SQL+代码生成类封装+测试类)
45 0
|
9月前
|
SQL 存储 Java
浅析 hive udaf 的正确编写方式- 论姿势的重要性
浅析 hive udaf 的正确编写方式- 论姿势的重要性
|
10月前
|
存储 关系型数据库 MySQL
MySQL的临时表以及视图与存储过程、触发器等功能概念详细解释说明以及它们的使用方法举例?
MySQL的临时表以及视图与存储过程、触发器等功能概念详细解释说明以及它们的使用方法举例?
|
JavaScript 前端开发 数据库
(简易)测试数据构造平台:36 - 复杂工具(页面自动获取数据模块)
(简易)测试数据构造平台:36 - 复杂工具(页面自动获取数据模块)
|
SQL 关系型数据库 MySQL
Loadrunner脚本优化-参数化之关联MySQL数据库获取数据
Loadrunner脚本优化-参数化之关联MySQL数据库获取数据
80 0
|
Java 关系型数据库 MySQL
JMeter 参数化之利用JDBCConnectionConfiguration从数据库读取数据并关联变量
JMeter 参数化之利用JDBCConnectionConfiguration从数据库读取数据并关联变量
123 0
|
SQL Oracle 关系型数据库
基于变量方式实现kettle快速循环迁移表数据(八)
基于变量方式实现kettle快速循环迁移表数据(八)
300 0
基于变量方式实现kettle快速循环迁移表数据(八)