Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add text search where clause to SPARQL query

Tags:

sparql

jena

I have been given what I thought would be a simple task - take an existing SPARQL query and adapt the WHERE clause to restrict results to entities where a specific text field contains a specific search term.

However, I am entirely new to the SPARQL language and nothing I've tried is working. It seems I need to use the text:query (rdfs:label 'word' 10) syntax, but I haven't managed to successfully integrate this into the query below.

What I need is to further filter the results of the below query where the rdfs:label triple has a value containing the search term. If any of you could provide guidance about how I need to change the query I'd be very grateful.

SELECT DISTINCT * WHERE 
{
  { SELECT  ?object ?label ?accessionNumber ?image  WHERE {
      ?object a my:Object .
      ?object my:accessionNumber ?accessionNumber .
      ?object  rdfs:label ?label .
      ?object my:maker <http://id.my.org.uk/agent/1234> .  
  }}  

  OPTIONAL  { 
    ?object my:preferredAsset ?asset .
    ?asset a my:Asset .
    ?asset dcterms:hasVersion ?image .
    ?image my:role 'thumbnail' .  
  }  
} 

Thanks in advance.

like image 644
Tom Troughton Avatar asked Aug 06 '14 15:08

Tom Troughton


People also ask

Which clauses in SPARQL can be used to match partial information in an RDF graph?

The query consists of two parts: the SELECT clause identifies the variables to appear in the query results, and the WHERE clause provides the basic graph pattern to match against the data graph.

What is a prefix in SPARQL query?

"PREFIX", however (without the "@"), is the SPARQL instruction for a declaration of a namespace prefix. It allows you to write prefixed names in queries instead of having to use full URIs everywhere. So it's a syntax convenience mechanism for shorter, easier to read (and write) queries.

What is bind in SPARQL?

BIND. SPARQL's BIND function allows us to assign a value to a variable.


1 Answers

Approximate Matching

String Matching

Joshua Taylor's comment points out an excellent and elegant solution to do exactly what you asked for:

filter contains( lcase(?label), "word").

You can also use regular expressions via the REGEX Filter Function. You would simply add an additional filter to your query such as:

FILTER regex(?label, "*word*", "i") .

This would allow you to retrieve all labels that contain word (case-insensitive).

Jena Text

The syntax text:query (rdfs:label 'word' 10) you mentioned is part of the jena-text project. Note that you must configure jena-text for it to work. The primary time that you want to use that is if you want to perform approximate text matching ie: if it's acceptable to search for word and get back things like words or wordpress etc.

Exact Matching

Another alternative is exact matching. You can do this by specifying an initial binding, or by modifying your query directly.

Query Modification

Modifying your query would produce one of several variations. Not all of these variations are considered equal (Plain Literals / Language Literals / Typed Literals), so you need to be careful when searching to know that your data will match.

 ?object  rdfs:label "word" .
 ?object  rdfs:label '''word''' .
 ?object  rdfs:label "word"@en .
 ?object  rdfs:label "word"^^xsd:string .

Binding Specification

Constructing an initial binding usually looks something like this (psuedocode):

final QuerySolutionMap initialBinding = new QuerySolutionMap(){{
     this.add("?label", model.createTypedLiteral(someString));
}};
final QueryExecution e = 
         QueryExecutionFactory.create(query,model,initialBinding);

Note that the second argument to add has the same choices as the query modification. You can create a language literal or a plain literal rather than a typed literal. Again, it needs to match your underlying data.

like image 172
Rob Hall Avatar answered Sep 19 '22 17:09

Rob Hall