这个SPARQL更新可以简化吗?

问题描述 投票:0回答:1

更新用于将 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)
      }
  }

我认为它做了我需要它做的事情,但我想知道是否有一种方法可以使它更加紧凑,而我现在还没有看到。

sparql rdf
1个回答
1
投票

显然可以将

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
}
© www.soinside.com 2019 - 2024. All rights reserved.