How to isolate a list of URIs in a RDF file using CONSTRUCT or DESCRIBE in SPARQL?

Danilo Moreira Source

I'm trying to get only a list of URIs in RDF instead of a list of triples:

PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

DESCRIBE  ?product 
WHERE
{
  ?product rdfs:subClassOf gr:ProductOrService .
}

Using SELECT, instead of DESCRIBE I receive only the subject (which I want), but not as an RDF but like a SPARQL Result with binds, vars, etc.

Using CONSTRUCT, I can't specify only the ?product, as above, so the closest I can get is:

PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

CONSTRUCT
WHERE
{
  ?product rdfs:subClassOf gr:ProductOrService .
}

Which returns an RDF with triples of different products, but the same properties and objects.

selectsparqlrdf

Answers

answered 6 months ago TallTed #1

It looks like you should read over the SPARQL specification, which tells you that this is exactly as expected. To get the single column you wish, you must use SELECT.

SPARQL has four query forms. These query forms use the solutions from pattern matching to form result sets or RDF graphs. The query forms are:

  • SELECT
    Returns all, or a subset of, the variables bound in a query pattern match.
  • CONSTRUCT
    Returns an RDF graph constructed by substituting variables in a set of triple templates.
  • ASK
    Returns a boolean indicating whether a query pattern matches or not.
  • DESCRIBE
    Returns an RDF graph that describes the resources found.

answered 6 months ago Danilo Moreira #2

I found a solution. I've used SELECT, but instead of binds and vars, as output received a "Comma-Separated Values (with fields in N-Triples syntax)" CSV file:

<http://www.productontology.org/id/Real_estate>
<http://www.productontology.org/id/Automobile>
<http://www.productontology.org/id/Auction>
<http://www.productontology.org/id/Video_game>
<http://www.productontology.org/id/Campsite>
<http://www.productontology.org/id/Car>
<http://www.productontology.org/id/Audiobook>
<http://www.productontology.org/id/Browser_game>
...

answered 6 months ago Jeen Broekstra #3

Representing the result of a SPARQL SELECT query as an RDF List is a tooling issue - it is not something that can be solved in SPARQL in general.

Some SPARQL tools may have ways to support rendering the query result as an RDF list. But it's not something you can fix by just formulating your query differently, you'll need to use a tool to (programmatically) format the result.

In Java, using Eclipse RDF4J, you can do it as follows (untested so you may need to tweak it to work properly, but it should give you a general idea):

String query = "SELECT ?product WHERE {  ?product rdfs:subClassOf gr:ProductOrService . }";

// do the query on repo and convert to a Java list of URI objects     
List<URI> results = Repositories.tupleQuery(
  repo, 
  query, 
  r -> QueryResults.stream(r).map(bs -> (URI)bs.getValue("product")).collect(Collectors.toList()
);

// create a resource (bnode or URI) for the start of the rdf:List
Resource head = SimpleValueFactory.getInstance().createBNode();

// convert the Java list of results to an rdf:list and add it 
// to a newly-created RDF Model
Model m = RDFCollections.asRDF(results, head, new LinkedHashModel());

Once you have your result as an RDF model you can use any of the existing RDF4J APIs to write it to file or to store it in a triplestore.

Now, I am not claiming that any of this is a good idea - I have never seen a use case for something like this. But this is how I would do it if it were necessary.

comments powered by Disqus