Reputation: 1023
I have a construct query in SPARQL which is useful to retrieve details about contracts:
CONSTRUCT {
?contract dcterm:identifier ?id .
?contract rdfs:label ?label .
?contract pc:bidder ?bidder .
}
WHERE {
OPTIONAL {
?contract dcterm:identifier ?id .
}
OPTIONAL {
?contract rdfs:label ?label .
}
OPTIONAL {
?contract pc:tender ?tender .
?tender pc:bidder ?bidder .
}
}
I have a list of contracts, for example pc:c1, pc:c2, and I would like to retrieve in one single query (or one single HTTP call) the details of both of them.
The first idea is to replace the ?contract variable with each uri and avoid conflicts between other variables:
CONSTRUCT {
pc:c1 dcterm:identifier ?id1 .
pc:c1 rdfs:label ?label1 .
pc:c1 pc:bidder ?bidder1 .
pc:c2 dcterm:identifier ?id2 .
pc:c2 rdfs:label ?label2 .
pc:c2 pc:bidder ?bidder2 .
}
WHERE {
OPTIONAL {
pc:c1 dcterm:identifier ?id1 .
}
OPTIONAL {
pc:c1 rdfs:label ?label1 .
}
OPTIONAL {
?pc:c1 pc:tender ?tender1 .
?tender1 pc:bidder ?bidder1 .
}
OPTIONAL {
pc:c2 dcterm:identifier ?id2 .
}
OPTIONAL {
pc:c2 rdfs:label ?label2 .
}
OPTIONAL {
?pc:c2 pc:tender ?tender2 .
?tender2 pc:bidder ?bidder2 .
}
}
The problem is that with many uris the query could become quite big.
Is there a more compact way to write it?
I tried with the IN operator ( https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping - 17.4.1.9 ) but Virtuoso doesn't seem to parse the query. Alse the VALUES keyword ( https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#inline-data ) seemed a good solution, but Jena doesn't seem to parse it correctly.
Upvotes: 3
Views: 89
Reputation: 85923
Just use values to specify the values of ?contract that you want. (Jena does support values, so maybe there was a typo in your test?) Here's what it would look like:
CONSTRUCT {
?contract dcterm:identifier ?id .
?contract rdfs:label ?label .
?contract pc:bidder ?bidder .
}
WHERE {
VALUES ?contract { pc:c1 pc:c2 } #-- this is the new line
OPTIONAL {
?contract dcterm:identifier ?id .
}
OPTIONAL {
?contract rdfs:label ?label .
}
OPTIONAL {
?contract pc:tender ?tender .
?tender pc:bidder ?bidder .
}
}
For the single property matches, you can also make this shorter with values for the properties. You can also use a property path to make the bidder part shorter:
CONSTRUCT {
?contract ?p ?o .
?contract pc:bidder ?bidder .
}
WHERE {
VALUES ?contract { pc:c1 pc:c2 }
VALUES ?p { dcterm:identifier rdfs:label }
OPTIONAL {
?contract ?p ?o
}
OPTIONAL {
?contract pc:tender/pc:bidder ?bidder .
}
}
Upvotes: 4