Search code examples
javasparqljenageosparql

optimizing a SPARQL query when using a custom function in Jena


I have the following SPARQL query on a Owl Ontology, using Jena:

SELECT ?label ?distance
WHERE {
  ?wpt rdf:type inav:Waypoint .
  ?wpt inav:Label ?label .
  ?ac  rdf:type inav:Aircraft .
  ?ac  inav:Label "myAircraft" .
  ?wpt inav:hasExactGeometry ?geom .
  ?geom inav:asWKT ?wkt .
  ?ac inav:hasExactGeometry ?geom2 .
  ?geom2 inav:asWKT ?wkt2 .
  BIND (geof:distance(?wkt, ?wkt2, <http://www.opengis.net/def/uom/OGC/1.0/nauticalMile>) as ?distance)
}
ORDER BY ASC(?distance )
LIMIT 1

The idea is that:

  • I have an Aircraft called "myAircraft"
  • I have several Waypoints
  • I search for the closest Waypoint using GeoSPARQL
  • I want to return the label of the closest Waypoint, and it's distance to the "myAircraft" Aircraft

This query works without any problem.

Now I am adding a custom vocabulary using Jena FunctionFactory. In my case I want to retrieve in real time the visibility of the meteo in meters at the position of the waypoint (to take an example). In order to do that, I created a custom vocabulary with one visibility word. It has only one argument which is the Label of the Waypoint in my case.

I then changed my query as following:

SELECT ?label ?distance ?visibility
WHERE {
  ?wpt rdf:type inav:Waypoint .
  ?wpt inav:Label ?label .
  ?ac  rdf:type inav:Aircraft .
  ?ac  inav:Label "myAircraft" .
  ?wpt inav:hasExactGeometry ?geom .
  ?geom inav:asWKT ?wkt .
  ?ac inav:hasExactGeometry ?geom2 .
  ?geom2 inav:asWKT ?wkt2 .
  BIND (geof:distance(?wkt, ?wkt2, <http://www.opengis.net/def/uom/OGC/1.0/nauticalMile>) as ?distance)
  BIND (my:visibility(?wpt) as ?visibility)
}
ORDER BY ASC(?distance )
LIMIT 1

It also works without any problem, but I remarked in my Debugger that the Java visibility function is called for every Waypoint in the Ontology, not only the closest one. If I have a lot of waypoints, I will have to call my Java function for Waypoint, when ideally I would like to do that for only one of them, the closest one.

Is there a way to do that to speed-up this query? (the idea is that in real-life I would call a meteo service for my Waypoint, but I do not want to do that for every Waypoint, but only the one I found in my query).


Solution

  • Per the very informative answer of UninformedUser:

    SELECT ?label ?distance ?visibility  
    {
       {SELECT ?label ?distance  
        WHERE {   
          ?wpt rdf:type inav:Waypoint .   
          ?wpt inav:Label ?label .  
          ?ac  rdf:type inav:Aircraft . 
          ?ac  inav:Label "myAircraft" . 
          ?wpt inav:hasExactGeometry ?geom .   
          ?geom inav:asWKT ?wkt .   
          ?ac inav:hasExactGeometry ?geom2 .   
          ?geom2 inav:asWKT ?wkt2 .   
          BIND (geof:distance(?wkt, ?wkt2, <http://www.opengis.net/def/uom/OGC/1.0/nauticalMile>) as ?distance)  
       } ORDER BY ASC(?distance ) LIMIT 1
    }  BIND (my:visibility(?wpt) as ?visibility)
    }