如何在 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。
我正在使用 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。