使用 Apache Jena 进行地理空间查询

Geospatial queries with Apache Jena

我在 Apache Jena 中开始进行地理空间查询时遇到问题。

收到@AndyS 的评论后,我意识到我需要从我的耶拿模型创建一个空间数据集。我仍然得到一个空结果

首先,在我的模型中,我有一组三元组:

<rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
        xmlns:ssn="http://purl.oclc.org/NET/ssnx/ssn#"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema#" > 
   <ssn:ObservationValue rdf:about="http://example.com/ObservationValues/GasCO/1450439142">
            <geo:location>
              <rdf:Description rdf:about="http://example.com/locations/GasCO/1450439142">
                <geo:lat>35.4</geo:lat>
                <geo:long>32</geo:long>
              </rdf:Description>
            </geo:location>
    <!-- here go more triples -->
    </ssn:ObservationValue>
    </rdf:RDF>

我正在尝试使用以下代码获取 ssn:ObservationValue 资源:

String queryStr =
    "PREFIX spatial: <http://jena.apache.org/spatial#> " +
    "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> " +
    "PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> " +
    "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> " +
    "PREFIX ssn: <http://purl.oclc.org/NET/ssnx/ssn#>" +
    "SELECT ?loc " +
    "WHERE {?loc spatial:nearby(35.4 32  1000 'km' )}";

    // creating entity definition. Should somehow define the geodata
    //EntityDefinition entDef = new EntityDefinition("ssn:ObservationValue",
    // "geo:location");
    // EntityDefinition entDef = new EntityDefinition(" <http://example.com/ObservationValues/GasCO/1450439142>",
    // "<http://example.com/locations/GasCO/1450439142>");
    EntityDefinition entDef = 
    new EntityDefinition("<http://purl.oclc.org/NET/ssnx/ssn#ObservationValue>",
    "<http://www.w3.org/2003/01/geo/wgs84_pos#location>");

    // Model m is a Jena Model object which contains the data
    Dataset baseDataset = DatasetFactory.create(m);

    try {
            Directory dir = FSDirectory.open( new File("/home/martin/spatial_index"));  
    Dataset spatialDataset = SpatialDatasetFactory.createLucene(baseDataset, dir, entDef); 

            Query query = QueryFactory.create(queryStr) ;
            QueryExecution qexec = QueryExecutionFactory.create(query, spatialDataset);
            ResultSet results = qexec.execSelect() ;
            System.out.println("results.size(): " + results.getRowNumber());
    } catch (IOException e) {
            e.printStackTrace();
    }

但结果集结果为空- results.getRowNumber() returns 0

我怀疑上面代码的问题是 EntityDefinition entDef 的定义。在 EntityDefinition 的文档中,它声明它期望 entityFieldgeoField 。我试图提供我感兴趣的节点的显式 IRI,前缀类型,例如ssn:Observationvalue 和 geo:location(如评论代码所建议的那样),但到目前为止,这两种解决方案都没有奏效。

有没有人遇到过类似的情况或有任何提示可能出了什么问题?

Apache Jena 邮件列表中的人员向我介绍了 spatialindexer.java 的源代码。事实证明,我需要手动将要索引的三元组添加到空间索引中。在这里,我提供了带有索引的源代码。它对我有用——上面的 SPARQL 查询在给定半径内找到三元组。修改后的代码为:

String queryStr =
  "PREFIX spatial: <http://jena.apache.org/spatial#> " +
  "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> " +
  "PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> " +
  "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> " +
  "PREFIX ssn: <http://purl.oclc.org/NET/ssnx/ssn#> " +
  "SELECT ?loc ?lat " +
  "WHERE {?loc spatial:nearby(35.5 32 1000 'km' ) . ?loc geo:lat ?lat}";

Model m = SemanticSensorModel.getIntance().getJenaModel();
EntityDefinition entDef = new EntityDefinition("1", "2");    
Dataset baseDataset = DatasetFactory.create(m);
try {
 Directory dir = FSDirectory.open( new File("/home/martin/spatial_index"));
 Dataset spatialDataset = SpatialDatasetFactory.createLucene(baseDataset, dir, entDef); 
   
 DatasetGraphSpatial dataset = (DatasetGraphSpatial) (spatialDataset.asDatasetGraph());
 SpatialIndex spatialIndex = dataset.getSpatialIndex();
 SpatialIndexContext context = new SpatialIndexContext(spatialIndex);
 spatialIndex.startIndexing();
    
 Iterator<Quad> quadIter = dataset.find(Node.ANY, Node.ANY, Node.ANY, Node.ANY);
 for (; quadIter.hasNext();) {
  Quad quad = quadIter.next();
  context.index(quad.getGraph(), quad.getSubject(), quad.getPredicate(), quad.getObject());
 }
 spatialIndex.finishIndexing();
       
 Query query = QueryFactory.create(queryStr) ;
 QueryExecution qexec = QueryExecutionFactory.create(query, spatialDataset);
 ResultSet results = qexec.execSelect() ;

 for ( ; results.hasNext() ; )
 {
  QuerySolution soln = results.nextSolution() ;
  System.out.println(soln.get("loc").toString() + " " + soln.get("lat").toString());
 }
    
 System.out.println("Done printing results");
} catch (IOException e) {
 e.printStackTrace();
}

注意 SpatialIndex 的创建,以及 startIndexing()/index()/finishIndexing() 方法的使用。 上面的代码可以作为任何人的起点 想从 Jena 的地理空间 SPARQL 查询开始。

此致

马丁