三元组组合的递归 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.
让我们使用 rdflib,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()
而不是第二个查询。
我有以下查询,我在 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.
让我们使用 rdflib,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()
而不是第二个查询。