4

I have some named graphs stored in Virtuoso, and I want to find the one that matches the highest number of terms from a provided list.

My query is constructed programatically and looks like this:

SELECT DISTINCT ?graph (count(DISTINCT ?match) as ?matches)
WHERE {
  GRAPH ?graph {
    {?match rdf:label "term 1"} 
     UNION {?match rdf:label "term 2"} 
     UNION {?match rdf:label "term 3"}
     ...
  }
}
ORDER BY DESC(?matches)

Each term becomes another UNION clause.

Is there a better way to do this? The query gets long and ugly fast, and Virtuoso complains when there are too many terms.

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
heyitsbmo
  • 1,715
  • 1
  • 14
  • 29

3 Answers3

4

In SPARQL 1.1, there's a values clause that can help out with this. It lets you write:

select ?match where {
  values ?label { "term 1" "term 2" "term 3" }
  ?match rdfs:label ?label
}
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • This solution is also faster than `FILTER`. For one example on Wikidata, `VALUES` are 15 times faster. Although the number of returned rows differs by few percent. – Anton Tarasenko May 24 '20 at 14:33
3

(it's rdfs:label)

An alternative way to write it is:

{ ?match rdfs:label ?X . FILTER (?x in ("term 1", "term 2", "term 3")) }

or (SPARQL 1.0)

{ ?match rdfs:label ?X . FILTER ( ?x = "term 1" || ?x = "term 2" || ?x = "term 3" )  }
AndyS
  • 16,345
  • 17
  • 21
  • An alternative is to use SPARQL 1.1's newer VALUES. Not sure if this was available when answering, but could be worth an update to the answer. – Nick Bartlett Nov 26 '13 at 17:59
1

The values solution is even more powerful as it allows the use of UNDEF as follows (e.g.):

VALUES (?s ?p ?o) { (<http://abc#X> <http://abc#P1> UNDEF)
                    (UNDEF <http://abc#P2> <http://abc#Y>) }

UNDEF has a wildcard function and the returned set of triplets is the union of matching each value triplet individually. But of course for large datasets it might be to slow from a performance point of view

Hubert Schumacher
  • 1,683
  • 1
  • 16
  • 25