how to use Union/or in sparql path with arbitrary

2019-07-20 09:08发布

问题:

I'm using below query to find all properties with domain of city (or superclasses of city) or range of country (or superclasses of country) from DBPedia ontology. when I use path with fixed length there is no problem but when I put * to define paths with arbitrary length, I get this error:

Virtuoso 37000 Error SP031: SPARQL compiler: Variable '_::trans_subj_6_4' is used in subexpressions of the query but not assigned

my SPARQL:

define sql:signal-void-variables 1
define input:default-graph-uri <http://dbpedia.org>

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX res: <http://dbpedia.org/resource/>
PREFIX owl:<http://www.w3.org/2002/07/owl#>
PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>

select ?property where{
  { ?property rdfs:domain/^rdfs:subClassOf* dbo:City }
  UNION
  { ?property rdfs:range/^rdfs:subClassOf* dbo:Country } 
}

Also when I put any number instead of *, I get same error. I'm using Virtuoso as DBPedia SPARQL endpoint.

回答1:

Use VALUES instead of UNION (when you can)

The error Virtuoso is giving you is more about its implementation of property paths and union than the actual SPARQL query. The SPARQL part of the query looks correct. (I can't speak to the Virtuoso specific defines.)

In many places that required union in the original SPARQL standard, you can now use values to specify the particular values that variables can have. It typically leads to more readable queries (at least, in my opinion), and some endpoints, such as Virtuoso, seem to handle it better.

Using values (and using the dbpedia-owl prefix that the web interface to the endpoint uses), you query becomes the following, and Virtuoso returns what you're looking for:

select ?property where {
  values (?p ?v) { (rdfs:domain dbpedia-owl:City)
                   (rdfs:range dbpedia-owl:Country) }
  ?property ?p ?class  .
  ?class ^rdfs:subClassOf* ?v .
}

SPARQL results

Other Notes

Also when I put any number instead of *, I get same error. I'm using Virtuoso as DBPedia SPARQL endpoint.

While Virtuoso accepts the {n,m} notation for lengths of property paths, do be aware that while those appeared in some drafts of property paths, they didn't actually make it into the SPARQL 1.1 standard. Virtuoso still accepts them, but if you use them, you might not be able to use your query with other endpoints.