如何使用SPARQL查询SUMO本体?

4

我正在使用SUMO本体,想要用SPARQL进行查询。SUMO中一个典型的条目,比如城市,看起来像这样:

<owl:Thing rdf:ID="MadridSpain">
 <rdfs:isDefinedBy rdf:resource="http://www.ontologyportal.org/SUMO.owl"/>
 <rdf:type rdf:resource="#City"/>
 <owl:comment xml:lang="en">The City of Madrid in Spain.</owl:comment>
 <geographicSubregion rdf:resource="#Spain" />
 <externalImage rdf:datatype="xsd:anyURI">[...]</externalImage>
 <rdfs:label xml:lang="en">madrid spain</rdfs:label>
</owl:Thing>

如果我想从本体中获取所有城市,我可以使用以下示例查询(这个查询运行良好):
String prefix = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
              + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>";
String rdq = prefix + "SELECT ?N ?O WHERE {?N rdf:type <http://www.ontologyportal.or/SUMO.owl#City>}";

当我想筛选结果时,问题就开始了。假设我只想要所有位于西班牙地理子区域的城市。首先,我尝试通过Java和Jena分析所有结果来解决这个问题,但这需要大量时间(每个结果需要5-10秒,总共约10000个结果)。

Query myQuery = QueryFactory.create(rdq);
QueryExecution qexec = QueryExecutionFactory.create(myQuery, owlModel);
try {
 ResultSet results = qexec.execSelect();
 for (; results.hasNext();) {
  QuerySolution sol = results.nextSolution();
  Resource res = sol.getResource("N");
  StmtIterator it = res.listProperties();

  while(it.hasNext()){
   Statement state = it.next();
   //Doing some filtering
   System.out.println("predicate: " + state.getPredicate().toString());
   System.out.println("subject: " + state.getSubject().toString());
   System.out.println("object: " + state.getObject().toString());
  }
 }
}catch (Exception e) {
 e.printStackTrace();
 System.err.println("Query Error " + e.getMessage());
}

当然,这并不是一个特别有效的方法,必须要使用正确的查询才能更加简单易懂。但目前我正在尝试定义这样一个查询,但我尝试了以下查询,但没有一个能够正常工作。

SELECT ?N ?O WHERE { ?N rdf:type <http://www.ontologyportal.org/SUMO.owl#City> . 
 { SELECT ?N WHERE { (rdf:type ?b rdf:statement) .
 (rdf:Predicate ?b <http://www.ontologyportal.org/SUMO.owl#geographicSubregion>) .
 (rdf:Object ?b <http://www.ontologyportal.org/SUMO.owl#Spain>) } } }

SELECT ?N ?O WHERE { (rdf:statement ?b) .
 (rdf:Predicate ?b <http://www.ontologyportal.org/SUMO.owl#geographicSubregion>) . 
 (rdf:Object ?b <http://www.ontologyportal.org/SUMO.owl#Spain>) . }";

有没有人有创造一个查询,获取一个国家内所有城市的想法?


你在这方面有进展吗?我几年前接触过SUMO,不知道有OWL翻译,所以很有趣。如果到目前为止的答案没有帮助,你还遇到了哪些其他问题? - Joshua Taylor
你的解决方案很好,对于这个出色的答案再加一分。 - FredFloete
很高兴能够帮助!正如我所说,我之前并不知道SUMO的OWL翻译,所以这对我来说是一个好消息。感谢你的询问! - Joshua Taylor
1个回答

5

我使用你提供的RDF创建了一个最小的RDF文件,我可以对其进行查询:

<rdf:RDF xmlns="http://www.ontologyportal.org/SUMO.owl#"
         xml:base="http://www.ontologyportal.org/SUMO.owl"
         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
         xmlns:owl="http://www.w3.org/2002/07/owl#"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <owl:Thing rdf:ID="MadridSpain">
    <rdfs:isDefinedBy rdf:resource="http://www.ontologyportal.org/SUMO.owl"/>
    <rdf:type rdf:resource="#City"/>
    <owl:comment xml:lang="en">The City of Madrid in Spain.</owl:comment>
    <geographicSubregion rdf:resource="#Spain" />
    <externalImage rdf:datatype="xsd:anyURI">[...]</externalImage>
    <rdfs:label xml:lang="en">madrid spain</rdfs:label>
  </owl:Thing>
</rdf:RDF>

SPARQL是一种用于匹配RDF图中数据的查询语言。RDF图中的边是“三元组”,即“主语谓语宾语”的简单语句。您正在针对单个三元组进行匹配。

?N rdf:type <http://www.ontologyportal.org/SUMO.owl#City>

如果您为 sumo: 定义一个前缀,那么按照目前的查询方式会更容易编写代码(同时将?N 重命名为 ?city):

prefix sumo: <http://www.ontologyportal.org/SUMO.owl#>
select ?city where { 
  ?city rdf:type sumo:City .
}

这选择了所有的城市,就像你之前看到的一样。现在你只需要匹配一个额外的三元组,所以我们只需将其添加到查询中:

prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix sumo: <http://www.ontologyportal.org/SUMO.owl#>
select ?city where { 
  ?city rdf:type sumo:City .
  ?city sumo:geographicSubregion sumo:Spain .
}

为了让这个更好看,可以应用两个缩写词。首先,在SPARQL中,“rdf:type”可以写成“a”,因为它很常见(然后我们也不需要定义前缀了)。其次,当您有多个与相同主题的三元组时,您可以将“谓语对象”部分以分号分隔的方式列出。我们最终得到:
prefix sumo: <http://www.ontologyportal.org/SUMO.owl#>
select ?city where { 
  ?city a sumo:City ;
        sumo:geographicSubregion sumo:Spain .
}

当我使用Jena的命令行工具对上面的RDF运行此操作时,我会得到以下结果:
$ arq --data sumo.rdf --query query.sparql
--------------------
| city             |
====================
| sumo:MadridSpain |
--------------------

为什么其他查询不起作用

您试图执行的类似操作如下:

(rdf:type ?b rdf:statement) .
(rdf:Predicate ?b <http://www.ontologyportal.org/SUMO.owl#geographicSubregion>) .
(rdf:Object ?b <http://www.ontologyportal.org/SUMO.owl#Spain>)

我将使用RDF再现词汇来进行翻译。首先,语法需要被优化。
?b a rdf:Statement ;
   rdf:subject ?city ;
   rdf:predicate sumo:geographicSubregion ;
   rdf:object sumo:Spain .

为了匹配一个特定形式的实例三元组,以回答你的查询需求。然而,这个查询需要图中有四个满足指定格式的三元组,但是这些三元组在模型中并不存在。仅仅因为一个三元组在图中出现,并不意味着它的实例化版本也在其中。(毕竟,既然用于实例化第一个三元组的所有三元组都必须被实例化,然后那些三元组也会被实例化,这样一直下去。) SPARQL 只能让你查询实际存在于数据中的三元组。

非常感谢您的好评。您的解决方案非常有效。也感谢您为了解释我的错误而额外付出努力。 - FredFloete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接