package org.com.plugin;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.script.ScriptEngine;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.SearchScript;
import org.apache.lucene.index.LeafReaderContext;
import org.elasticsearch.search.lookup.LeafDocLookup;
import org.elasticsearch.index.fielddata.ScriptDocValues;
public class Hamming extends Plugin implements ScriptPlugin{
@Override
public ScriptEngine getScriptEngine(Settings settings, Collection<ScriptContext<?>> contexts) {
return new MyExpertScriptEngine();
}
private static class MyExpertScriptEngine implements ScriptEngine {
@Override
public String getType() {
return "expert_scripts";
}
@Override
public <T> T compile(String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> params) {
if (context.equals(SearchScript.CONTEXT) == false) {
throw new IllegalArgumentException(getType() + " scripts cannot be used for context [" + context.name + "]");
}
if ("Hamming".equals(scriptSource)) {
SearchScript.Factory factory = (p, lookup) -> new SearchScript.LeafFactory() {
private Set<Map.Entry> pms = ((Map)p.get("m")).entrySet();
private double d_diff = Double.valueOf((String)p.get("diff"));
@Override
public SearchScript newInstance(LeafReaderContext context) throws IOException {
return new SearchScript(p, lookup, context) {
@Override
public double runAsDouble() {
double d_res = 0D;
LeafDocLookup ldl = getDoc();
if (null == ldl) {
return -1D;
}
for(Map.Entry e : pms){
String s = (String)e.getKey();
long l_t;
try {
l_t = (long)e.getValue();
} catch (ClassCastException ccex) {
l_t = (int)e.getValue();
}
try {
ScriptDocValues.Longs l_s = (ScriptDocValues.Longs)ldl.get(s);
d_res += hammingDistance(l_t, l_s.getValue());
} catch (Exception ex){
return -1D;
}
if (d_res > d_diff) {
return -1D;
}
};
return d_res;
}
};
}
@Override
public boolean needs_score() {
return false;
}
private double hammingDistance(long x, long y) {
double cnt = 0D;
long hamming = x ^ y;
while(hamming > 0) {
hamming = hamming & (hamming - 1);
cnt += 1;
}
return cnt;
}
};
return context.factoryClazz.cast(factory);
}
throw new IllegalArgumentException("Unknown script name " + scriptSource);
}
@Override
public void close() {
}
}
}
调用
{
"_source": [
"id"
],
"query": {
"function_score": {
"functions": [
{
"script_score": {
"script": {
"source": "Hamming",
"lang": "expert_scripts",
"params": {
"m":{
"f_0": 19210667227652650,
"f_1": 2305843013508960000
},
"diff":"500"
}
}
}
}
]
}
}
}
参数和字段要对上 (数据中要有f_0 ,f_1)字段