更新用于将 RDF 序列中的一项(source)移至另一项(target),并相应地重新计算序列索引。无论源最初出现在目标之前还是之后,它都必须紧邻结果中的目标之后放置。您可以将其想象为拖放操作。
序列的示例如下所示:
<https://linkeddatahub.com/demo/northwind-traders/>
a <https://w3id.org/atomgraph/linkeddatahub/default#Root> ;
rdf:_1 <https://linkeddatahub.com/demo/northwind-traders/#page-header> ;
rdf:_2 <https://linkeddatahub.com/demo/northwind-traders/#top-selling-products> ;
rdf:_3 <https://linkeddatahub.com/demo/northwind-traders/#top-manager-header> ;
rdf:_4 <https://linkeddatahub.com/demo/northwind-traders/#top-manager> ;
rdf:_5 <https://linkeddatahub.com/demo/northwind-traders/#select-children> .
SPARQL 更新:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX ldh: <https://w3id.org/atomgraph/linkeddatahub#>
PREFIX ac: <https://w3id.org/atomgraph/client#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
DELETE {
$this ?sourceSeq $sourceContent .
$this ?targetSeq $targetContent .
$this ?seq ?content .
}
INSERT {
$this ?newSourceSeq $sourceContent .
$this ?newTargetSeq $targetContent .
$this ?newSeq ?content .
}
WHERE
{ $this ?sourceSeq $sourceContent
BIND(xsd:integer(substr(str(?sourceSeq), 45)) AS ?sourceIndex)
$this ?targetSeq $targetContent
BIND(xsd:integer(substr(str(?targetSeq), 45)) AS ?targetIndex)
BIND(if(( ?sourceIndex < ?targetIndex ), ( ?targetIndex - 1 ), ?targetIndex) AS ?newTargetIndex)
BIND(if(( ?sourceIndex < ?targetIndex ), ?targetIndex, ( ?targetIndex + 1 )) AS ?newSourceIndex)
BIND(IRI(concat(str(rdf:), "_", str(?newSourceIndex))) AS ?newSourceSeq)
BIND(IRI(concat(str(rdf:), "_", str(?newTargetIndex))) AS ?newTargetSeq)
OPTIONAL
{ { $this ?sourceSeq $sourceContent
BIND(xsd:integer(substr(str(?sourceSeq), 45)) AS ?sourceIndex)
$this ?targetSeq $targetContent
BIND(xsd:integer(substr(str(?targetSeq), 45)) AS ?targetIndex)
$this ?seq ?content
FILTER strstarts(str(?seq), str(rdf:_))
BIND(xsd:integer(substr(str(?seq), 45)) AS ?index)
FILTER ( ( ?index > ?sourceIndex ) && ( ?index < ?targetIndex ) )
BIND(( ?index - 1 ) AS ?newIndex)
}
UNION
{ $this ?sourceSeq $sourceContent
BIND(xsd:integer(substr(str(?sourceSeq), 45)) AS ?sourceIndex)
$this ?targetSeq $targetContent
BIND(xsd:integer(substr(str(?targetSeq), 45)) AS ?targetIndex)
$this ?seq ?content
FILTER strstarts(str(?seq), str(rdf:_))
BIND(xsd:integer(substr(str(?seq), 45)) AS ?index)
FILTER ( ( ?index < ?sourceIndex ) && ( ?index > ?targetIndex ) )
BIND(( ?index + 1 ) AS ?newIndex)
}
BIND(IRI(concat(str(rdf:), "_", str(?newIndex))) AS ?newSeq)
}
}
我认为它做了我需要它做的事情,但我想知道是否有一种方法可以使它更加紧凑,而我现在还没有看到。
显然可以将
UNIION
替换为 ||
:
BIND (?index > ?sourceIndex && ?index < ?targetIndex AS ?isBetweenSourceAndTarget)
BIND (?index < ?sourceIndex && ?index > ?targetIndex AS ?isBetweenTargetAndSource)
FILTER (?isBetweenSourceAndTarget || ?isBetweenTargetAndSource)
BIND (?index + if(?isBetweenSourceAndTarget, -1, +1) AS ?newIndex)
BIND (IRI(concat(str(rdf:), "_", str(?newIndex))) AS ?newSeq)
但也许重新计算更简单all
rdf:_n
:
DELETE { $this ?seq ?content }
INSERT { $this ?newSeq ?content }
WHERE {
SELECT $this ?seq ?content (IRI(concat(str(rdf:_), str(count(*)))) AS ?newSeq) {
$this ?sourceSeq $sourceContent .
BIND (xsd:decimal(strafter(str(?sourceSeq), '_')) AS $sourceIndex)
$this ?targetSeq $targetContent
BIND (xsd:decimal(strafter(str(?targetSeq), '_')) AS $targetIndex)
$this ?seq ?content . FILTER strstarts(str(?seq), str(rdf:_))
BIND (xsd:decimal(strafter(str(?seq), '_')) AS ?oldIndex)
BIND (IF(?content = $sourceContent, $targetIndex + 0.5, ?oldIndex) AS ?newIndex)
$this ?seq_ ?content_ . FILTER strstarts(str(?seq_), str(rdf:_))
BIND (xsd:decimal(strafter(str(?seq_), '_')) AS ?oldIndex_)
BIND (IF(?content_ = $sourceContent, $targetIndex + 0.5, ?oldIndex_) AS ?newIndex_)
FILTER (?newIndex >= ?newIndex_)
}
GROUP BY $this ?seq ?content
}