0

我在 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 (?age)

Stardog 是否以不同的方式解释规范,或者这是我不知道的功能?

另一个问题是,我们在 CONSTRUCT 查询中使用了自定义聚合函数 (stdev),而且通过 Stardog API 似乎可以正常工作。虽然我们的大部分代码都是基于 Jena 的,但它似乎无法识别自定义 stdev 功能。我猜是因为这个扩展只与 Stardog 相关并且对 Jena 不可用?让我举个例子。ATM,我们正在通过以下 Jena 代码执行 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 查询中指定要操作的命名图。没有什么能像 Jena 模型那样代表数据库的一部分,这样我们就可以避免在查询中指定它。这里有什么好的方法?

所以我的问题是双重的:为什么在 Stardog 中查询的解析方式不同,是否可以让 Jena 检测到自定义 Stardog 聚合函数?谢谢!

更新

最后,我们试图完成的是对给定的命名图执行构造查询,但将新构造的三元组写入不同的图。在我的 Jena 示例中,您可以看到我正在使用两个 Jena 模型来实现这一点。您将如何使用 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);
}
4

3 回答 3

2

错误的可能原因

SELECT 中的非组键变量:表达式中的 ?age (?age)

是不是 SPARQL 验证器和 ARQ 不知道这agg:stardog:stdev是一个聚合,也不以这种方式解释它。(?x + ?y as ?sum)正如 AndyS 所指出的,语法与标准投影表达式没有什么不同,例如。

虽然 SPARQL 规范并没有完全排除自定义聚合,但它们并没有在语法本身中考虑。Stardog 和 Jena 都允许自定义聚合,尽管方式不同。

另一个问题是,我们在 CONSTRUCT 查询中使用了自定义聚合函数 (stdev),而且通过 Stardog API 似乎可以正常工作。虽然我们的大部分代码都是基于 Jena 的,但它似乎无法识别自定义 stdev 功能。我猜是因为这个扩展只与 Stardog 相关并且对 Jena 不可用?

是的,Jena 和 Stardog 是不同的。您在 Stardog 中定义的任何自定义内容(例如自定义聚合)都不能直接在 Jena 中使用。

您可能正在以这样一种方式构建模型,即通过 ARQ,Jena 是查询引擎,而不是 Stardog。这可以解释为什么您会遇到 Jena 不知道您在 Stardog 中定义的自定义聚合的异常。

没有什么能像 Jena 模型那样代表数据库的一部分,这样我们就可以避免在查询中指定它。这里有什么好的方法?

您可以使用数据集通过 SNARL API 以编程方式指定查询的活动图

所以我的问题是双重的:为什么在 Stardog 中查询的解析方式不同,是否可以让 Jena 检测到自定义 Stardog 聚合函数?谢谢!

它们的解析方式不同,因为没有定义自定义聚合的标准方法,而 Stardog & Jena 选择以不同方式实现它。此外,Jena 不会知道 Stardog 的自定义聚合,反之亦然。

于 2016-03-07T17:28:13.490 回答
1

SELECT 中的非组键变量:表达式中的 ?age (?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 规范,对吗?

于 2016-03-07T16:44:18.083 回答
0

除非安装了自定义聚合,否则解析器不知道它是聚合。默认情况下,Apache Jena ARQ 没有自定义聚合。

URI 聚合看起来像一个普通的自定义函数。因此,如果您尚未安装该聚合,则解析器会将其视为自定义函数。

AVG 强制进行隐式分组,因此自定义函数位于非组键变量上,这是非法的。

于 2016-03-07T17:18:34.700 回答