三元组组合的递归 SPARQL 查询

Recursive SPARQL query for a combination of triples

我有以下查询,我在 Python 中使用 ontospy 递归地 运行:

SELECT ?c WHERE {
    ?c rdfs:subClassOf ?restriction .
    ?restriction owl:onProperty :has_part ; owl:someValuesFrom ?p .
    VALUES ?p { <some_uri> }
}

基本上,我获取从中返回的值并重新运行 查询以遵循ontology 中"has part some" 关系的层次结构。我希望通过将递归添加到查询本身来避免进行多个 SPARQL 查询。我知道如何使用 rdfs:subClassOf* 对单个三元组执行此操作,但无法弄清楚组合两个三元组的语法:

?c rdfs:subClassOf ?restriction .
?restriction owl:onProperty :has_part ; owl:someValuesFrom ?p .

这可能吗?

我不能给出正式的证明,但这看起来是不可能的。这不是 属性 路径的设计目的,也不是某些扩展存在的原因 (1, 2)。

在某些承诺下(例如 tree-like 结构), 使用 FILTER NOT EXISTS 来解决问题,但这不是通用的解决方案。

我们的想法是在两个查询中执行此操作。从本质上讲,这是 SELECT 超过 CONSTRUCT。顺便说一句,这样的SPARQL扩展已经proposed.


让我们使用 ,Ontospy 是基于它的,因为

Ontospy does not offer any ontology-editing features, nor it can be used to interrogate a triplestore.

输入(ontology.ttl)

@prefix : <http://www.example.org/ontology#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www.example.org/ontology> .

<http://www.example.org/ontology> rdf:type owl:Ontology .

:hasPart rdf:type owl:ObjectProperty .

:Country rdf:type owl:Class ;
         rdfs:subClassOf [ rdf:type owl:Restriction ;
                           owl:onProperty :hasPart ;
                           owl:someValuesFrom :State
                         ] .

:State rdf:type owl:Class ;
       rdfs:subClassOf [ rdf:type owl:Restriction ;
                         owl:onProperty :hasPart ;
                         owl:someValuesFrom :City
                       ] .

:City rdf:type owl:Class .

Python代码

import rdflib

g = rdflib.Graph()
g.parse("ontology.ttl", format="n3")

qres = g.update(
    """PREFIX : <http://www.example.org/ontology#> 
       INSERT { ?c :hasSome ?p } 
       WHERE  { ?c rdfs:subClassOf [ owl:onProperty :hasPart ; 
                                     owl:someValuesFrom ?p ] }""")

qres = g.query(
    """PREFIX : <http://www.example.org/ontology#> 
       SELECT ?a ?b WHERE {?a :hasSome+ ?b }""")

for row in qres:
    print("%s :hasSome+ %s" % row)

qres = g.update(
    """PREFIX : <http://www.example.org/ontology#> 
       DELETE { ?s :hasSome ?o } WHERE { ?s :hasSome ?o }""")

输出

:Country :hasSome+ :State
:State   :hasSome+ :City
:Country :hasSome+ :City

如果您不想修改初始 RDFLib 图,只需创建另一个:

import rdflib

g1 = rdflib.Graph()
g1.parse("ontology.ttl", format="n3")

qres = g1.query(
    """PREFIX : <http://www.example.org/ontology#> 
       CONSTRUCT {?c :hasSome ?p } WHERE {
           ?c rdfs:subClassOf [ owl:onProperty :hasPart ;
                                owl:someValuesFrom ?p  ] }""")

g2 = rdflib.Graph();
for triple in qres: # quite a few triples
    g2.add(triple)

qres = g2.query(
    """PREFIX : <http://www.example.org/ontology#> 
       SELECT ?a ?b WHERE { ?a :hasSome+ ?b }""")

for row in qres:
    print("%s :hasSome+ %s" % row)

在这两种情况下,您可能可以使用 transitiveClosure() or transitive_objects() 而不是第二个查询。