我在Stardog中创建了一个自定义聚合函数来计算标准偏差。当您将 SPARQL 查询发布到端点或通过管理控制台中的查询面板时,这非常有效。
到目前为止,一切顺利,但我们面临几个问题。首先,当我们执行如下所示的查询时,它将通过Stardog完美执行,但在SPARQL验证器(以及Jena API)中会失败:
PREFIX : <http://our/namespace#>
PREFIX agg: <urn:aggregate:>
SELECT (agg:stardog:stdev(?age) AS ?stdLMD) (AVG(?age) AS ?avg)
WHERE {
?pat a :Person .
?pat :age ?age .
}
Stardog给出了标准差和平均年龄的正确结果,但SPARQL验证器抛出了一个异常:
SELECT 中的非组键变量:表达式中的年龄(?age)
Stardog是否以不同的方式解释规范,或者这是一个我不知道的功能?
另一个问题是,我们在CONSTRUCT查询中使用了自定义聚合函数(stdev),并且似乎通过Stardog API工作正常。不过,我们的大多数代码都是基于 Jena,它似乎无法识别自定义的 stdev 功能。我猜是因为这个扩展只与星狗有关,对耶拿不可用?让我举一个例子。ATM,我们通过以下耶拿代码执行 CONSTRUCT查询:
final Query dbQuery = QueryFactory.create(query.getContent());
final QueryExecution queryExec = QueryExecutionFactory.create(dbQuery, model);
queryExec.execConstruct(infModel);
只要我们不使用聚合函数,这就像一个魅力。由于我们在多个命名图中构造三元组,因此也有一个可用的模型(表示命名图)非常方便。
我想用Stardog java API做类似的事情。我只做到了:
UpdateQuery dbQuery;
try {
dbQuery = connection.update(query.getContent());
dbQuery.execute();
} catch (final StardogException e) {
LOGGER.error("Cannot execute CONSTRUCT query", e);
}
问题是您明确需要指定要在 CONSTRUCT查询中操作的命名图。没有什么比耶拿模型更能表示数据库的一部分了,因此我们可以避免在查询中指定它。这里有什么好方法?
所以我的问题是双重的:为什么在Stardog中解析查询的方式不同,是否可以让Jena检测自定义Stardog聚合函数?谢谢!
更新
最后,我们试图完成的是,对给定的命名图执行构造查询,但将新构造的三元组写入不同的图。在我的耶拿示例中,您可以看到我正在使用两个耶拿模型来实现这一点。您将如何使用SNARL API执行此操作?我已经得到了以下代码片段,但这只定义了此查询将针对的数据集,而不是三元组将写入的位置。对此的任何帮助仍然不胜感激!
UpdateQuery dbQuery;
try {
dbQuery = connection.update(query.getContent());
final DatasetImpl ds = new DatasetImpl();
ds.addNamedGraph(new URIImpl(infDatasource));
dbQuery.dataset(ds);
dbQuery.execute();
} catch (final StardogException e) {
LOGGER.error("Cannot execute CONSTRUCT query", e);
}
错误的可能原因
SELECT 中的非组键变量:表达式中的年龄(?age)
是SPARQL验证器和ARQ不知道agg:stardog:stdev
是一个聚合,并且不以这种方式解释它。正如AndyS所指出的,语法与标准投影表达式(如(?x + ?y as ?sum)
)没有什么不同。
虽然SPARQL规范并没有完全排除自定义聚合,但它们并未在语法本身中考虑。 Stardog和Jena都允许自定义聚合,尽管方式不同。
是另一个问题是,我们在CONSTRUCT查询中使用了自定义聚合函数(stdev),并且似乎通过Stardog API工作正常。不过,我们的大多数代码都是基于 Jena,它似乎无法识别自定义的 stdev 功能。我猜是因为这个扩展只与星狗有关,对耶拿不可用?
的,耶拿和星狗是不同的。您在 Stardog 中定义的任何自定义内容(例如自定义聚合)都不会直接在耶拿中使用。
您可能正在以这样的方式构建模型,即耶拿通过 ARQ 成为查询引擎,而不是 Stardog。这可以解释为什么你会收到耶拿不知道你在Stardog中定义的自定义聚合的异常。
没有什么比耶拿模型更能表示数据库的一部分了,因此我们可以避免在查询中指定它。这里有什么好方法?
您可以使用数据集通过 SNARL API 以编程方式指定查询的活动图
所以我的问题是双重的:为什么在Stardog中解析查询的方式不同,是否可以让Jena检测自定义Stardog聚合函数?谢谢!
它们的解析方式不同,因为没有定义自定义聚合的标准方法,Stardog & Jena 选择以不同的方式实现它。此外,耶拿不会知道Stardog的定制聚合,反之亦然。
SELECT 中的非组键变量:表达式中的年龄(?age)
Stardog对规范的解释是否不同,或者这是一个 我不知道的功能?
我认为您正确阅读了规范,并且验证器可能只是无法识别非内置聚合。 规范说:
19.8 语法
聚合函数可以是聚合的内置关键字之一,也可以是自定义聚合,后者在语法上是函数调用。聚合函数只能在 SELECT、HAVING 和 ORDER BY 子句中使用。
至于构造查询:
你另一个问题是,我们在CONSTRUCT查询中使用了自定义聚合函数(stdev),并且似乎通过Stardog API工作正常。不过,我们的大多数代码都是基于 Jena,它似乎无法识别自定义 stdev 函数。
没有提到你如何使用这个。 若要在构造模式中使用聚合,需要使用子查询。 例如,像这样:
construct { ?s :hasStandardDeviation ?stddev }
where {{
select ?s (agg:stddev(?value) as ?stddev) {
?s :hasSampleValue ?value
}
group by ?s
}}
在 CONSTRUCT/WHERE 的 SPARQL 函数中有一些这样的例子。 当然,如果验证者拒绝第一个,它可能也会拒绝第二个,但看起来它实际上应该是合法的。 对于Jena,您可能需要确保选择允许扩展的查询语言,但由于规范允许自定义函数(当由IRI识别时),我认为您应该能够使用标准的SPARQL 1.1语言。 您使用的是SPARQL 1.1,而不是早期的SPARQL规范,对吗?
除非安装了自定义聚合,否则解析器不知道它是一个聚合。 默认情况下,Apache Jena ARQ 没有自定义聚合。
按 URI 聚合看起来像一个普通的自定义函数。因此,如果您尚未安装该聚合,则解析器会将其视为自定义函数。
AVG 强制隐式分组,因此自定义函数位于非组键变量上,这是非法的。