Java SPARQL中带有Jena API的自定义函数

Java SPARQL中带有Jena API的自定义函数,java,sparql,jena,Java,Sparql,Jena,第一次在这里发帖。我希望有人能帮我定制SPARQL函数,以便在Jena(ARQ)API中使用。我需要SPARQL进行一些聚合,我知道它已经实现了avg、count、min、max和sum,但我还需要能够实现标准偏差和中位数(我还需要range,但这可以通过使用min和max来实现) 我希望查询可以类似于您对已实现的函数所使用的查询: PREFIX example: <http://www.examples.com/functions#> PREFIX core: <http

第一次在这里发帖。我希望有人能帮我定制SPARQL函数,以便在Jena(ARQ)API中使用。我需要SPARQL进行一些聚合,我知道它已经实现了avg、count、min、max和sum,但我还需要能够实现标准偏差和中位数(我还需要range,但这可以通过使用min和max来实现)

我希望查询可以类似于您对已实现的函数所使用的查询:

PREFIX example: <http://www.examples.com/functions#>  
PREFIX core: <http://www.core.com/values#>  
SELECT (stddev(?price) as ?stddev)  
WHERE {  
    ?s core:hasPrice ?price  
}  
前缀示例:
前缀核心:
选择(STDEV(?价格)作为?STDEV)
何处{
?s核心:hasPrice?price
}  
我不知道这是否可行,但如果我需要像其他自定义函数一样使用它,只要它仍然得到结果的标准偏差,就可以了

我所知道的是,这些函数将用Java编写,我已经非常了解Java。所以,我想知道是否有人知道这方面的好方法,或者从哪里开始寻找一些指导。我试着寻找关于它的文档,但似乎什么都没有。任何帮助都将不胜感激


提前感谢。

是的,ARQ可以以多种方式扩展。这将是最好的起点。

我不确定你能在不改变语法的情况下做你想做的事

例如,SUM(…)是SPARQL语法定义的关键字:

筛选函数或属性函数可能不是您想要的


顺便说一下,您也不会在SQL中获得STDDEV。这是因为需要对数据进行两次传递吗?

聚合函数是SPARQL(因此也是ARQ)函数的特例。 我认为在ARQ中,扩展聚合函数集并不容易,而扩展过滤函数集和属性函数集却很容易(并且有文档记录)。 你可以用这样的方法计算标准偏差:

PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
PREFIX core: <http://www.core.com/values#>  
SELECT ( afn:sqrt( sum( (?price - ?avg) * (?price - ?avg) ) / (?count - 1) ) as ?stddev )  
WHERE {
  ?s core:hasPrice ?price .
  {  
    SELECT (avg(?price) as ?avg) (count(*) as ?count) 
    WHERE {  
      ?s core:hasPrice ?price
    }
  }
}  
前缀afn:
前缀核心:
选择(afn:sqrt(总和((?价格-?平均值)*(?价格-?平均值))/(计数-1))作为STDEV)
在哪里{
?的核心:hasPrice?price。
{  
选择(平均价格)作为平均值(计数(*)作为计数)
何处{
?s核心:hasPrice?price
}
}
}  

无论如何,我不得不使用afn:sqrt,这是SPARQL 1.1草案中没有的ARQ“专有”函数,因此此查询在不同于Jena的框架上不起作用。

ARQ允许您通过在
aggregatereRegistry
中注册来添加自己的聚合函数。该示例显示了如何实现这一点。这可用于添加问题中要求的自定义标准偏差聚合函数。在下面的示例中,用于进行计算

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.jena.graph.Graph;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.expr.aggregate.Accumulator;
import org.apache.jena.sparql.expr.aggregate.AccumulatorFactory;
import org.apache.jena.sparql.expr.aggregate.AggCustom;
import org.apache.jena.sparql.expr.aggregate.AggregateRegistry;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.graph.NodeConst;
import org.apache.jena.sparql.sse.SSE;

public class StandardDeviationAggregate {
    /**
     * Custom aggregates use accumulators. One accumulator is created for each group in a query execution.
     */
    public static AccumulatorFactory factory = (agg, distinct) -> new StatsAccumulator(agg);

    private static class StatsAccumulator implements Accumulator {
        private AggCustom agg;
        private SummaryStatistics summaryStatistics = new SummaryStatistics();

        StatsAccumulator(AggCustom agg) { this.agg = agg; }

        @Override
        public void accumulate(Binding binding, FunctionEnv functionEnv) {
            // Add values to summaryStatistics
            final ExprList exprList = agg.getExprList();
            final NodeValue value = exprList.get(0).eval(binding, functionEnv) ;
            summaryStatistics.addValue(value.getDouble());
        }

        @Override
        public NodeValue getValue() {
            // Get the standard deviation
            return NodeValue.makeNodeDouble(summaryStatistics.getStandardDeviation());
        }
    }

    public static void main(String[] args) {
        // Register the aggregate function
        AggregateRegistry.register("http://example/stddev", factory, NodeConst.nodeMinusOne);

        // Add data
        Graph g = SSE.parseGraph("(graph " +
                "(:item1 :hasPrice 13) " +
                "(:item2 :hasPrice 15) " +
                "(:item3 :hasPrice 20) " +
                "(:item4 :hasPrice 30) " +
                "(:item5 :hasPrice 32) " +
                "(:item6 :hasPrice 11) " +
                "(:item7 :hasPrice 16))");

        Model m = ModelFactory.createModelForGraph(g);
        String qs = "PREFIX : <http://example/> " +
                    "SELECT (:stddev(?price) AS ?stddev) " +
                    "WHERE { ?item :hasPrice ?price }";

        // Execute query and print results
        Query q = QueryFactory.create(qs) ;
        QueryExecution qexec = QueryExecutionFactory.create(q, m);
        ResultSet rs = qexec.execSelect() ;
        ResultSetFormatter.out(rs);
    }
}
import org.apache.commons.math3.stat.description.SummaryStatistics;
导入org.apache.jena.graph.graph;
导入org.apache.jena.query.*;
导入org.apache.jena.rdf.model.model;
导入org.apache.jena.rdf.model.ModelFactory;
导入org.apache.jena.sparql.engine.binding.binding;
导入org.apache.jena.sparql.expr.ExprList;
导入org.apache.jena.sparql.expr.NodeValue;
导入org.apache.jena.sparql.expr.aggregate.acculator;
导入org.apache.jena.sparql.expr.aggregate.累加器工厂;
导入org.apache.jena.sparql.expr.aggregate.AggCustom;
导入org.apache.jena.sparql.expr.aggregate.AggregateRegistry;
导入org.apache.jena.sparql.function.FunctionEnv;
导入org.apache.jena.sparql.graph.NodeConst;
导入org.apache.jena.sparql.sse.sse;
公共类标准偏差合计{
/**
*自定义聚合使用累加器。在查询执行中为每个组创建一个累加器。
*/
公共静态蓄能器工厂=(agg,独立)->新静态蓄能器(agg);
专用静态类StatsAccumulator实现累加器{
私人agg;
私有SummaryStatistics SummaryStatistics=新的SummaryStatistics();
StatsAccumulator(AggCustom agg){this.agg=agg;}
@凌驾
公共无效累积(绑定绑定、FunctionEnv FunctionEnv){
//向summaryStatistics添加值
final ExprList ExprList=agg.getExprList();
final NodeValue=exprList.get(0.eval)(binding,functionEnv);
summaryStatistics.addValue(value.getDouble());
}
@凌驾
公共节点值getValue(){
//得到标准差
返回NodeValue.makeNodeDouble(summaryStatistics.getStandardDiversion());
}
}
公共静态void main(字符串[]args){
//注册聚合函数
AggregateRegistry.register(“http://example/stddev“、工厂、NodeConst.nodeMinusOne);
//添加数据
图g=SSE.parseGraph(“(图)”+
“(:项目1:hasPrice 13)”+
“(:项目2:hasPrice 15)”+
“(:项目3:hasPrice 20)”+
“(:项目4:hasPrice 30)”+
“(:item5:hasPrice 32)”+
“(:项目6:hasPrice 11)”+
“(:item7:hasPrice 16))”;
模型m=ModelFactory.createModelForGraph(g);
String qs=“前缀:”+
“选择(:stddev(?price)作为?stddev)”+
“其中{?项目:hasPrice?price}”;
//执行查询并打印结果
Query q=QueryFactory.create(qs);
QueryExecution qexec=QueryExecutionFactory.create(q,m);
ResultSet rs=qexec.execSelect();
结果格式输出(rs);
}
}

我希望这个例子至少能帮助一些人,即使这个问题是几年前发布的。

这是有帮助的,但是我如何使用他们的max函数示例来找到一组结果的max值呢?(max示例位于)谢谢,在看了更多内容后,您似乎是对的,我不想要过滤器或属性函数。话虽如此,我还有什么办法可以挽救吗