我使用以下自定义 ARQ 函数成功实现了 sparql 查询(自定义函数代码):
public class LevenshteinFilter extends FunctionBase2 {
public LevenshteinFilter() { super() ; }
public NodeValue exec(NodeValue value1, NodeValue value2){
LevenshteinDistance LD=new LevenshteinDistance();
int i = LD.apply(value1.asString(), value2.asString());
return NodeValue.makeInteger(i);
}
}
当我查询从乌龟文件加载的模型时,它工作正常,如下所示:
InputStream input = QueryProcessor.class.getClassLoader().getResourceAsStream("full.ttl");
model = ModelFactory.createMemModelMaker().createModel("default");
model.read(input,null,"TURTLE"); // null base URI, since model URIs are absolute
input.close();
像这样发送查询:
String functionUri = "http://www.example1.org/LevenshteinFunction";
FunctionRegistry.get().put(functionUri , LevenshteinFilter.class);
String s = "whatever you want";
String sparql = prefixes+" SELECT DISTINCT ?l WHERE { ?x rdfs:label ?l . " + "FILTER(fct:LevenshteinFunction(?l, \"" + s + "\") < 4) }";
Query query = QueryFactory.create(sparql);
QueryExecution qexec = QueryExecutionFactory.create(query, model);
ResultSet rs = qexec.execSelect();
但是,如果我对同一个数据集(full.ttl)使用一个有效的 fuseki 端点,如下所示:
fusekiUrl="http://localhost:3030/ds/query";
发送这样的查询(使用QueryExecutionFactory.sparqlService(fusekiUrl,query)而不是QueryExecutionFactory.create(query,model)):
String functionUri = "http://www.example1.org/LevenshteinFunction";
FunctionRegistry.get().put(functionUri , LevenshteinFilter.class);
String s = "whatever you want";
String sparql = prefixes+" SELECT DISTINCT ?l WHERE { ?x rdfs:label ?l . " + "FILTER(fct:LevenshteinFunction(?l, \"" + s + "\") < 4) }";
Query query = QueryFactory.create(sparql);
QueryExecution qexec = QueryExecutionFactory.sparqlService(fusekiUrl,query);
ResultSet rs = qexec.execSelect();
然后我没有得到任何结果。在这两种情况下,我都打印出了 FunctionRegistry ,它们包含完全相同的条目,尤其是:
键= http://www.example1.org/LevenshteinFunction 值:org.apache.jena.sparql.function.FunctionFactoryAuto@5a45133e
有什么线索吗?
谢谢
回到我终于解决的那个问题。有几个问题,其中一个是(显然!!)远程端点和客户端在不同的 jvm 上运行。
要使事情正常工作,请执行以下操作(对于愚蠢的 MyFilter 自定义函数 - 即 strlen):
1)在fuseki服务器上部署自定义函数类jar
2) 修改 fuseki 配置:
add [] ja:loadClass "my.functions.package.MyFilter"
MyFilter 实现在哪里:
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.function.FunctionBase1;
public class MyFilter extends FunctionBase1 {
public MyFilter() { super() ; }
public NodeValue exec(NodeValue value1){
int d = value1.asString().length();
return NodeValue.makeInteger(new Integer(d));
}
}
3)在上下文中添加以下前缀:
PREFIX f: <java:my.functions.package.>
请注意“my.functions.package”。是 MyFilter 类的包,而不是类本身 --> 这意味着您永远不会在 sparql 查询中调用类方法,而只会调用实现 org.apache.jena.sparql.function.FunctionBaseX 的类,其中 X 是参数的数量你的过滤功能
4)编写(例如)这样的查询:
SELECT DISTINCT ?l
WHERE { ?x skos:prefLabel ?l .
FILTER (f:MyFilter(?l) < 20)
}
编辑:步骤 2) 不是必需的