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

How to create a new variable in CONSTRUCT query

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

数据实际上是出处,但可以简化为这样的一系列关系: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)
    }
}

到这里为止一切都很好。但是,我想获得更多信息,比如 "which A is connected to which another A by what data",像这样:

: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?

中不起作用

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

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

这应该会产生所需的图形结构。如果你坚持使用 IRI 而不是影响节点的空白节点(你可能应该这样做),那么你会想要这样的东西:

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

这会将新的 IRI 分配给变量 ?influence 并在 CONSTRUCT 模板中使用该变量。

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