Skip to content

Multi‐value placeholders

Carlos Martinez edited this page Aug 7, 2024 · 2 revisions

Grlc queries usually work with one-on-one variable-value replacement. But there are instances in which you would like to replace multiple values into the same variable. This tutorial shows you how to achieve this.

For example the following example query creates an API which queries for albums of artists of a specific genre:

PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX schema: <http://schema.org/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?band ?album WHERE {
  ?band rdf:type dbo:Band .
  ?album rdf:type schema:MusicAlbum .
  ?band dbo:genre ?_genre_iri .
  ?album dbp:artist ?band .
} LIMIT 100

For example you could query for rock bands (replacing genre for http://dbpedia.org/resource/Rock_music) producing a list of rock bands and albums or you could query for alternative rock bands (replacing genre for http://dbpedia.org/resource/Alternative_rock) producing a list of alternative rock bands and albums

But there are instances in which you would like to replace multiple values into the same variable. For example, if you wanted to create a list of two genres (or three or four...), then you would need a different query. This can be accomplished using some crafty SPARQL.

For this example, lets try to create a list with rock and alternative rock bands.

You could use a query like this:

#+ summary: Multi-value placeholder hack
#+ endpoint: https://dbpedia.org/sparql
#+ defaults:
#+   - placeholder: http://dbpedia.org/resource/Alternative_rock http://dbpedia.org/resource/Rock_music

PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX schema: <http://schema.org/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?band ?album ?genre WHERE {

  #=================== MULTI-VALUE PLACEHOLDER ====================#
  { select ?genreliteral {                                         # <- VAR genreliteral
    bind(?_placeholder as ?v)                                      # <- VAR _placeholder
    {select*{optional{?a ?b ?c}}limit 1} # (for some Virtuoso v.)  #
    values ?x{0 1 2 3 4 5 6 7 8 9} values ?y{0 1 2 3 4 5 6 7 8 9}  #
    bind((10*?x)+?y as ?n) # (works for a maximum of 100 values)   #
    bind(" " as ?sep) # (separator as regex-compatible character)  # <- CONST sep
    bind(concat("^([^",?sep,"]*",?sep,"){",str(?n),"}") as ?p)     #
    bind(concat(?sep,".*") as ?p0)                                 #
    filter(if(?n=0,true,regex(?v,?p))) # (=0 check for Virtuoso)   #
    bind(replace(if(?n=0,?v,replace(?v,?p,"")),?p0,"") as ?genreliteral)  # <- VAR genreliteral
  } }                                                              #
  #================================================================#
  # The genreliteral is a literal. You can make a URI out of it like this:
  bind(uri(?genreliteral) as ?genre)
  #================================================================#

  ?band rdf:type dbo:Band .
  ?album rdf:type schema:MusicAlbum .
  ?band dbo:genre ?genre .
  ?album dbp:artist ?band .

} LIMIT 100

The variable ?_placeholder takes a literal of space-separated IRIs, which are then bound individually in the query. It has an upper limit of 100 IRIs.

This query creates an API with could produce our desired list of will produce producing a list of rock and alternative rock bands and albums

Although this is not (strictly speaking) a functionality that grlc provides, we thought this method could be useful for many grlc users.

Thanks to @tkuhn for contributing this method!

Clone this wiki locally