记录一次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


相关文章
|
6月前
|
SQL 分布式计算 MaxCompute
一种基于ODPS SQL的全局字典索引分布式计算思路
本文提供一种能充分利用分布式计算资源来计算全局字典索引的方法,以解决在大数据量下使用上诉方式导致所有数据被分发到单个reducer进行单机排序带来的性能瓶颈。
|
7月前
|
分布式计算 大数据 数据处理
MaxCompute操作报错合集之编写UDF(用户自定义函数)时,报错:找不到主类,是什么原因
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
176 1
|
6月前
|
SQL 数据库 UED
SQL查询功能的全面解析与实用技巧
SQL(Structured Query Language)作为数据库管理的核心语言,其查询功能是实现数据检索、分析和报告的关键
|
9月前
|
SQL 存储 分布式计算
Hive【基础知识 02-2】【Hive CLI 命令行工具使用】【详细举例-包含测试脚本文件】
【4月更文挑战第7天】Hive【基础知识 02-2】【Hive CLI 命令行工具使用】【详细举例-包含测试脚本文件】
154 0
|
9月前
|
SQL 搜索推荐 Java
Hive中的UDF是什么?请解释其作用和使用方法。
Hive中的UDF是什么?请解释其作用和使用方法。
126 0
|
9月前
|
SQL 数据采集 Java
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
99 0
|
存储 SQL 关系型数据库
Mysql数据库 11.SQL语言 储存过程 中 流程控制
Mysql数据库 11.SQL语言 储存过程 中 流程控制
88 0
|
SQL 存储 Java
浅析 hive udaf 的正确编写方式- 论姿势的重要性
浅析 hive udaf 的正确编写方式- 论姿势的重要性
|
SQL Oracle 关系型数据库
Mysql数据库基本操作语法命令归纳
Mysql数据库基本操作语法命令归纳
139 0
Mysql数据库基本操作语法命令归纳
|
数据库连接 数据库
无事来学学--Kettle中查询,流程,连接组件的使用(上)
查询组件 查询是转换里面的第七个分类。查询是用来查询数据源里的数据并合并到主数据流中。
579 0