记录一次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月前
|
Java
ETL工具 Kettle 中 kettle循环传递变量_(最简单的方法)
本文详细介绍了如何在Kettle工具中使用循环传递变量,通过示例展示了如何将movies表数据按月插入到ods_movies表,涉及新建转换、获取变量、作业配置和执行,呈现了一个嵌套作业结构.
176 3
|
5月前
|
缓存 索引
kibana上执行ES DSL语言查询数据并查看表结构与数据、删除索引、查看文件大小
kibana上执行ES DSL语言查询数据并查看表结构与数据、删除索引、查看文件大小
293 0
|
6月前
|
SQL 关系型数据库 数据库
Python执行PostgreSQL数据库查询语句,并打印查询结果
本文介绍了如何使用Python连接和查询PostgreSQL数据库。首先,确保安装了`psycopg2`库,然后创建数据库连接函数。接着,展示如何编写SQL查询并执行,例如从`employees`表中选取所有记录。此外,还讨论了处理查询结果、格式化输出和异常处理的方法。最后,提到了参数化查询和事务处理以增强安全性及确保数据一致性。
Python执行PostgreSQL数据库查询语句,并打印查询结果
|
7月前
|
SQL 存储 分布式计算
Hive【基础知识 02-2】【Hive CLI 命令行工具使用】【详细举例-包含测试脚本文件】
【4月更文挑战第7天】Hive【基础知识 02-2】【Hive CLI 命令行工具使用】【详细举例-包含测试脚本文件】
122 0
|
7月前
|
SQL 搜索推荐 Java
Hive中的UDF是什么?请解释其作用和使用方法。
Hive中的UDF是什么?请解释其作用和使用方法。
100 0
|
7月前
|
SQL BI 数据处理
Flink中的流式SQL是什么?请解释其作用和用途。
Flink中的流式SQL是什么?请解释其作用和用途。
139 0
|
7月前
|
SQL 数据采集 Java
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
Java【代码分享 02】商品全部分类数据获取(建表语句+Jar包依赖+树结构封装+获取及解析源代码)包含csv和sql格式数据下载可用
84 0
|
存储 SQL 关系型数据库
Mysql数据库 11.SQL语言 储存过程 中 流程控制
Mysql数据库 11.SQL语言 储存过程 中 流程控制
77 0
|
SQL 存储 Java
浅析 hive udaf 的正确编写方式- 论姿势的重要性
浅析 hive udaf 的正确编写方式- 论姿势的重要性

热门文章

最新文章

相关课程

更多