计算满足约束的值,并为那些在SPARQL中不满足约束的值返回0

时间:2014-08-14 19:44:26

标签: rdf sparql

我想使用SPARQL查询检测满足属性值条件的所有值。

例如,假设我想要检测rdfs:label的值类型为xsd:string的所有资源。

逻辑中的定义可以是:

∀x(stringLabel(x)≡∀y(rdfs:label(x,y)→xsd:string(y)))

我在SPARQL中找到了一种方法:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <http://example.org/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?s where {

  # Count arcs with property rdfs:label 
  { SELECT ?s (COUNT(*) AS ?c0) {
      ?s rdfs:label ?o . 
     } GROUP BY ?s
  } 
  # Count arcs with property rdfs:label and value xsd:string
  { SELECT ?s (COUNT(*) AS ?c1) {
     ?s rdfs:label ?o . FILTER ((isLiteral(?o) && datatype(?o) = xsd:string)) 
    } GROUP BY ?s
  }
  # filter out those resources that have rdfs:label 
  # with values not in xsd:string
  FILTER (?c0 = ?c1)
}

似乎可以使用以下数据:

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <http://example.org/> .

:peter rdfs:label "Peter" ;  foaf:knows :anna .

:anna rdfs:label "Anna" .

:r22 rdfs:label 22 .

:x foaf:knows :r22 .

但是,它不会返回值:x,因为它没有rdfs:label,并且它不会返回0作为计数c0

对于没有该属性的资源,有没有办法计算某些属性返回0的资源?

1 个答案:

答案 0 :(得分:2)

假设你有这样的数据,其中一些资源有rdfs:label值,有些没有,有些资源有一些有字符串值,有些有非字符串值。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <http://stackoverflow.com/q/25316358/1281433/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# a non-string label
:a rdfs:label 22 .

# one or more string labels
:b rdfs:label "hello"^^xsd:string .
:c rdfs:label "hello"^^xsd:string , "goodbye"^^xsd:string .

# no labels at all
:d rdfs:seeAlso :b .

您可以编写一个查询,然后通过匹配所有非文字资源开始,并过滤掉那些不符合指定条件的查询。也就是说,您只需过滤出那些标签不是xsd:string的那些。

prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <http://stackoverflow.com/q/25316358/1281433/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?s where {
  #-- initially select all non-literals
  ?s :? ?s 
  filter ( !isLiteral(?s) )

  #-- but filter out anything that has a
  #-- a non-string label
  filter not exists {
    ?s rdfs:label ?label 
    filter ( datatype(?label) != xsd:string )
  }
}
------
| s  |
======
| :c |
| :d |
| :b |
------

您当然可以计算结果数量:

prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <http://stackoverflow.com/q/25316358/1281433/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select (count(distinct ?s) as ?ns) where {
  ?s :? ?s 
  filter ( !isLiteral(?s) )
  filter not exists {
    ?s rdfs:label ?label 
    filter ( datatype(?label) != xsd:string )
  }
}

------
| ns |
======
| 3  |
------

或者,如果你想选择每个?以及它拥有的rdfs:标签的数量,你也可以通过选择?s所具有的标签,按?分组,以及计算不同的?标签值:

prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <http://stackoverflow.com/q/25316358/1281433/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?s (count(distinct ?label) as ?nlabel) where {
  ?s :? ?s 
  filter ( !isLiteral(?s) )
  filter not exists {
    ?s rdfs:label ?label 
    filter ( datatype(?label) != xsd:string )
  }

  #-- get the label for counting
  optional { 
    ?s rdfs:label ?label 
  }
}
group by ?s
---------------
| s  | nlabel |
===============
| :d | 0      |
| :b | 1      |
| :c | 2      |
---------------