基于Elasticsearch的自定义评分算法扩展(java版)
PublishedCreated: 2017年10月18日星期三 16:15:02 views(2069)
实现思路: 重写评分方法,调整计算文档得分的过程,然后根据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 .