获取一个地点的纬度和经度(使用DBpedia)

3

我想通过已知名称获取一个地点的纬度和经度。

PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT * WHERE {
  ?s a dbo:Place .
  ?s geo:lat ?lat .
  ?s geo:long ?long .
} 

如果地点的名称(?s)类似于Graves Park,那么该怎样在Jena中实现相同的功能呢?而如果地点的名称可能不同呢?


PREFIX geo:http://www.w3.org/2003/01/geo/wgs84_pos# PREFIX asd:http://dbpedia.org/page/ SELECT ?lati ?longi WHERE { asd:Graves_Park geo:long ?lati. asd:Graves_Park geo:lat ?longi. } 得到一个空结果。 - Kriss
“The DBpedia Dataset”中的“第3节。表示或命名‘事物’”(http://wiki.dbpedia.org/Datasets#h18-4)指出:“DBpedia数据集中的每个事物都由可反引用的IRI或基于URI的引用表示,其形式为http://dbpedia.org/resource/Name,其中Name来自源Wikipedia文章的URL。”例如,如果您对http://dbpedia.org/resource/Mount_Monadnock进行反引用,您将被重定向到http://dbpedia.org/page/Mount_Monadnock。 resource是实际的事物,而page只是包含有关它的信息的页面。如果您滚动到底部... - Joshua Taylor
在页面的底部,您会看到“CSV原始数据| RDF(…)| OData(…)| 微数据(…)| JSON-LD”链接。如果您选择其中一个RDF格式,例如N-Triples,您将看到所有的数据仍然与resource(资源)有关,而不是与页面有关。这有点像传记包含了很多关于一个人的信息;传记中的信息(在page上)不是关于传记(page)本身,而是关于这个人(resource)。 - Joshua Taylor
非常感谢。是的,现在事情清晰多了。 - Kriss
1个回答

3
你可以使用Jena的ARQ来对远程SPARQL端点执行查询。该过程在ARQ - Querying Remote SPARQL Services中有描述。

在SELECT查询中使用ParameterizedSparqlStrings

为了在不同的位置执行查询,可能需要在执行查询时才知道这些位置,您可以使用ParameterizedSparqlString来保存查询,然后在获得值后注入值。这是一个例子。查询是您提供的那个查询。我将其放入ParameterizedSparqlString中,然后使用setIri?s设置为http://dbpedia.org/resource/Mount_Monadnock
import com.hp.hpl.jena.query.ParameterizedSparqlString;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;

public class DBPediaQuery {
    public static void main( String[] args ) {
        final String dbpedia = "http://dbpedia.org/sparql";
        final ParameterizedSparqlString queryString
          = new ParameterizedSparqlString(
                    "PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>"+
                    "PREFIX dbo: <http://dbpedia.org/ontology/>" +
                    "SELECT * WHERE {" +
                    "  ?s a dbo:Place ." +
                    "  ?s geo:lat ?lat ." +
                    "  ?s geo:long ?long ." +
                    "}" );
        queryString.setIri( "?s", "http://dbpedia.org/resource/Mount_Monadnock");
        QueryExecution exec = QueryExecutionFactory.sparqlService( dbpedia, queryString.toString() );
        ResultSet results = exec.execSelect();
        ResultSetFormatter.out( System.out, results );
    }
}

这个打印的结果是:
--------------------------------------------------------------------------------------------------------------
| lat                                                 | long                                                 |
==============================================================================================================
| "42.8608"^^<http://www.w3.org/2001/XMLSchema#float> | "-72.1081"^^<http://www.w3.org/2001/XMLSchema#float> |
--------------------------------------------------------------------------------------------------------------

一旦您获得了ResultSet,就可以遍历解决方案的行并提取值。这里的值是Literal,从Literal中,您可以提取词汇形式(字符串值),或者相应Java类型的值(对于数字、字符串、布尔值等)。您可以执行以下操作来打印纬度和经度,而不使用ResultSetFormatter
while ( results.hasNext() ) {
  QuerySolution solution = results.next();
  Literal latitude = solution.getLiteral( "?lat" );
  Literal longitude = solution.getLiteral( "?long" );

  String sLat = latitude.getLexicalForm();
  String sLon = longitude.getLexicalForm();

  float fLat = latitude.getFloat();
  float fLon = longitude.getFloat();

  System.out.println( "Strings: " + sLat + "," + sLon );
  System.out.println( "Floats: " + fLat + "," + fLon );
}

这个变更后的输出是:
Strings: 42.8608,-72.1081
Floats: 42.8608,-72.1081

在CONSTRUCT查询中使用ParameterizedSparqlStrings

根据一些评论,使用CONSTRUCT查询将每个查询的结果保存起来,并将它们聚合成一个更大的模型也可能很有用。以下是使用构造查询检索Mount Monadnock和Mount Lafayette的纬度和经度,并将其存储在单个模型中的代码。(这里我们只是使用CONSTRUCT WHERE {…},因此返回的模型与匹配部分完全相同。您可以通过使用CONSTRUCT {…} WHERE {…}获得不同的结果。)

import com.hp.hpl.jena.query.ParameterizedSparqlString;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

public class DBPediaQuery {
  public static void main( String[] args ) {
    final String dbpedia = "http://dbpedia.org/sparql";
    final ParameterizedSparqlString queryString
      = new ParameterizedSparqlString(
            "PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>"+
            "PREFIX dbo: <http://dbpedia.org/ontology/>" +
            "CONSTRUCT WHERE {" +
            "  ?s a dbo:Place ." +
            "  ?s geo:lat ?lat ." +
            "  ?s geo:long ?long ." +
            "}" );
    Model allResults = ModelFactory.createDefaultModel();
    for ( String mountain : new String[] { "Mount_Monadnock", "Mount_Lafayette" } ) {
      queryString.setIri( "?s", "http://dbpedia.org/resource/" + mountain );
      QueryExecution exec = QueryExecutionFactory.sparqlService( dbpedia, queryString.toString() );
      Model results = exec.execConstruct();
      allResults.add( results );
    }
    allResults.setNsPrefix( "geo", "http://www.w3.org/2003/01/geo/wgs84_pos#" );
    allResults.setNsPrefix( "dbo", "http://dbpedia.org/ontology/" );
    allResults.setNsPrefix( "dbr", "http://dbpedia.org/resource/" );
    allResults.write( System.out, "N3" );
  }
}

输出显示了两个查询的三元组:
@prefix dbr:     <http://dbpedia.org/resource/> .
@prefix geo:     <http://www.w3.org/2003/01/geo/wgs84_pos#> .
@prefix dbo:     <http://dbpedia.org/ontology/> .

dbr:Mount_Lafayette
      a       dbo:Place ;
      geo:lat "44.1607"^^<http://www.w3.org/2001/XMLSchema#float> ;
      geo:long "-71.6444"^^<http://www.w3.org/2001/XMLSchema#float> .

dbr:Mount_Monadnock
      a       dbo:Place ;
      geo:lat "42.8608"^^<http://www.w3.org/2001/XMLSchema#float> ;
      geo:long "-72.1081"^^<http://www.w3.org/2001/XMLSchema#float> .

什么是在RDF三元存储中适当的存储方式?我正在寻找构建三元存储的方法,但无法理解它...我读到结果集只会在一次迭代中具有值,之后就会丢失。 - Kriss
如何将从上述查询中检索到的纬度存储到字符串中? - Kriss
@Kriss 关于第二条评论:我已经更新了答案,并提供了一个遍历结果集中解决方案的示例。 - Joshua Taylor
@Kriss:关于第一个评论:如果你想保存你检索到的数据,你可以使用CONSTRUCT查询而不是SELECT查询,并将结果图添加到本地模型中。如果这听起来是一个合适的选项,我可以更新答案。 - Joshua Taylor
@Kriss 我看了一下并回复了那个评论。 - Joshua Taylor
显示剩余2条评论

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