如何在CONSTRUCT查询中创建新变量

时间:2019-04-01 15:12:44

标签: sparql

我正在使用SPARQL将一个数据存储中的数据转换为另一种形式/本体/模式。

数据实际上是一个来源,但可以简化为一系列关系,例如:A produces D + B consumes D

:A0 :consumes :D0 ;
    :produces :D1, :D2 .
:A1 :produces :D3 .
:A2 :consumes :D1, :D2 ;
    :produces :D4 .
:A3 :consumes :D3, :D4 ;
    :produces :D5, D6 .

(不能保证D总是由某个A产生,或被其他A消耗。但是每个D只能由一个A产生。)

我想获取数据依赖性的信息。查询示例如下:

CONSTRUCT {
    ?producer :hasNextStage ?consumer .
}
WHERE {
    ?producer :produces ?data .
    OPTIONAL {
            ?consumer :consumes ?data .
            FILTER (?producer != ?consumer)
    }
}

一切都很好,直到这里。但是,我想了解更多信息,例如“通过数据将哪个A连接到另一个A”,

:A0 :hasInfluence :INFLUENCE .
:INFLUENCE :stage :A2 ;
    :data :D1, :D2 .

如所示,这需要我构造一个新变量(:INFLUENCE)并为其分配三元组。 有没有办法在SPARQL中做到这一点?

------更新后的问题------

根据cygri的回答,我将查询更改为:

CONSTRUCT {
    ?producer :hasInfluence ?influence .
    ?influence :stage ?consumer ;
        :data ?data .
}
WHERE {
    ?producer :produces ?data .
    OPTIONAL {
            ?consumer :consumes ?data .
            FILTER (?producer != ?consumer)
            BIND (IRI(CONCAT("http://my/ns/#", CONCAT(STRAFTER(STR(?producer), "#"), STRAFTER(STR(?consumer), "#")))) AS ?influence)
    }
}

但是,BIND子句似乎没有任何作用。缩短它后,问题出在?producer变量上:如果我在此使用此变量,它将无法正常工作。似乎?producer没有绑定在这里? (但是FILTER确实有效。)

如果我将此BIND子句移出OPTIONAL,一切正常。但这不是直观的,我想知道为什么它无法在OPTIONAL中使用?

1 个答案:

答案 0 :(得分:1)

最简单的解决方案是完全避免在CONSTRUCT模板中使用新变量,而只使用一个空白节点:

CONSTRUCT {
    ?producer :hasInfluence [
        :stage ?consumer;
        :data ?data
    ]
}

这将产生所需的图形结构。如果您坚持使用IRI代替影响节点的空白节点(您可能应该这样做),那么您将需要:

CONSTRUCT {
    ?producer :hasInfluence ?influence.
    ?influence :stage ?consumer;
        :data ?data.
}
WHERE {
    ...
    BIND (IRI(xxx) AS ?influence)
}

这将为变量?influence分配一个新的IRI,并在CONSTRUCT模板中使用该变量。

现在,xxx只是用于计算IRI的表达式的占位符。您没有提供足够的细节来说明应该包含的内容。每个数据节点都会有一个影响节点吗?如果是这样,您可以采用数据IRI的字符串形式:str(?data),并使用replace(s, search, replace)进行一些字符串替换,以为影响节点创建一个很好的唯一IRI。