基于Elasticsearch的自定义评分算法扩展 (转)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Elasticsearch的自定义评分算法扩展 (转)相关的知识,希望对你有一定的参考价值。
实现思路:
重写评分方法,调整计算文档得分的过程,然后根据function_score或script_sort进行排序检索。
实现步骤:
1、新建java项目TestProject,引入Elasticsearch的jar包
2、新建package:es.testscript
3、新建类TestScriptFactory,继承NativeScriptFactory,示例:
package es.testscript;
import java.util.Map;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;
/**
* Created by lijunhao on 2016/3/29.
*/
public class TestScriptFactory implements NativeScriptFactory {
@Override
public ExecutableScript newScript(@Nullable Map<String, Object> params) {
return new TestScript(params);
}
}
4、新建类TestScript,假设计算double类型的得分,继承AbstractDoubleSearchScript,并重写runAsDouble方法,示例:
package es.testscript;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.script.AbstractDoubleSearchScript;
import org.elasticsearch.script.AbstractLongSearchScript;
import java.util.Map;
public class TestScript extends AbstractDoubleSearchScript {
//客户端传递的参与动态计算得分的参数
private String[] paramArray;
/**
* 构造函数 获取传入的参数
*
* @param params
*/
public TestScript(@Nullable Map<String, Object> params) {
if (params == null || params.size() == 0) {
return;
}
Set<String> keys = params.keySet();
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String val = params.get(key).toString();
System.out.println("key:" + key + " val:" + val + "\r\n");
}
if (params.get("fields") == null) {
return;
}
paramArray = params.get("fields").toString().split(",");
System.out.println("fields:" + params.get("fields").toString() + "\r\n");
}
/**
* 排序方法,计算得分
*
* @return
*/
@Override
public double runAsDouble() {
double defaultReturnVal = Double.parseDouble(String.valueOf(((ScriptDocValues.Longs)doc().get("id")).getValue()));
if (paramArray == null || paramArray.length == 0) {
return defaultReturnVal;
}
//根据传入的paramArray计算得分
defaultReturnVal=defaultReturnVal+1000;
System.out.println("score:" + defaultReturnVal + "\r\n");
return defaultReturnVal;
}
}
5、打包输出jar文件TestProject.jar
6、将TestProject.jar拷贝至ES目录的lib下
7、修改ES配置文件elasticsearch.yml,添加:
script.native:
mynativescript.type: es.testscript.TestScriptFactory
注:mynativescript为自定义的脚本别名。
8、重启ES服务
9、执行检索:function_score方式
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"script_score": {
"script": "mynativescript",
"lang": "native",
"params": {
"p1": 1,
"fields": "p1,p2"
}
}
}
]
}
}
}
10、执行检索:script_sort方式
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"script": "mynativescript",
"lang": "native",
"order": "asc",
"type": "string",
"params": {
"p1": 1,
"p2": 2,
"p3": 3
}
}
}
}
11、执行检索:Nest方式之Linq
var s = new SearchDescriptor<ModelTest>().From(0).Size(20).MatchAll().SortScript(sort => sort
.Descending()
.Script("mynativescript")
.Descending()
.Params(p => p
.Add("p1", 1.1).Add("p2", 2.2)
)
.Language("native")
.Type("string")
);
//获取请求的json字符串
string reqStr = Encoding.UTF8.GetString(client.Serializer.Serialize(s));
ISearchResponse<ModelTest> resp = client.Search<ModelTest>(s);
ModelTest[] result = resp.Documents.ToArray();
12. Nest方式之Query对象
1 QueryContainer mainQuery = null; <br> FunctionScoreQuery funcQuery = new FunctionScoreQuery(); 2 funcQuery.ScoreMode = FunctionScoreMode.Sum; 3 funcQuery.BoostMode = FunctionBoostMode.Replace; 4 funcQuery.MaxBoost = 1000.0f; 5 IFunctionScoreFunction func = new FunctionScoreFunctionsDescriptor<DTOCarInfoIndexField>().ScriptScore(s => s.Lang("native").Script("mynativescript")); 6 IList<IFunctionScoreFunction> list = new List<IFunctionScoreFunction>(); 7 list.Add(func); 8 funcQuery.Functions = list; 9 mainQuery &= funcQuery; 10 11
以上是关于基于Elasticsearch的自定义评分算法扩展 (转)的主要内容,如果未能解决你的问题,请参考以下文章