Semweb4j/filesQueries/step4

From semanticweb.org

Jump to: navigation, search

Up | Previous step | Next step

Contents

[edit] Step 4: SPARQL SELECT

We will use the peopleTag from step3 (with a few changes) again, so the first lines of code are:

package org.ontoware.semweb4j.lessons.lesson2;

import org.ontoware.rdf2go.RDF2Go;
import org.ontoware.rdf2go.exception.ModelRuntimeException;
import org.ontoware.rdf2go.model.Model;
import org.ontoware.rdf2go.model.QueryResultTable;
import org.ontoware.rdf2go.model.QueryRow;
import org.ontoware.rdf2go.model.node.Node;
import org.ontoware.rdf2go.model.node.PlainLiteral;
import org.ontoware.rdf2go.model.node.Resource;
import org.ontoware.rdf2go.model.node.URI;
import org.ontoware.rdf2go.vocabulary.XSD;

public class Step4 {

	private static Model model;
	private static URI hasTag;
	
	private static void init() throws ModelRuntimeException {
		model = RDF2Go.getModelFactory().createModel();
		model.open();
	}
	
	public static void tag(Resource resource, Node tag) throws ModelRuntimeException {
		model.addStatement(resource, hasTag, tag);
	}
	

[edit] the main method, example setup

	public static void main(String[] args) throws ModelRuntimeException {

		init();

		// creating URIs
		// persons
		URI max = model.createURI("http://xam.de/foaf.rdf.xml#i");
		URI konrad = model.createURI("http://example.com/persons#konrad");
		URI guido = model.createURI("http://example.com/persons#guido");
		URI james = model.createURI("http://example.com/persons#james");
		// relations
		URI hasName = model.createURI("http://xmlns.com/foaf/0.1/#term_name");
		URI hasAge = model.createURI("http://example.com/relations#age");
		hasTag = model.createURI("http://example.com/relations#hasTag");
		// tags
		PlainLiteral tagJava = model.createPlainLiteral("Java");
		PlainLiteral tagPython = model.createPlainLiteral("Python");

We have the properties name, age and tag now, modeled by the relations hasName, hasAge and hasTag.

		// adding statements
		// naming
		model.addStatement(max, hasName, "Max Völkel");
		model.addStatement(konrad, hasName, "Konrad V");
		model.addStatement(guido, hasName, "Guido van Rossum");
		model.addStatement(james, hasName, "James Gosling");
		
		// a typed property, age
		model.addStatement(konrad, hasAge, model.createDatatypeLiteral("19", XSD._integer));
		model.addStatement(max, hasAge, model.createDatatypeLiteral("29", XSD._integer));
		
		// tagging
		tag(max, tagJava);
		tag(james, tagJava);
		tag(konrad, tagJava);
		tag(konrad, tagPython);
		tag(guido, tagPython);

Now we have named, tagged and also specified a datatyped age for some resources. This should be enough data to query with SPARQL.

[edit] simple SELECT queries

[edit] the SELECT query in RDF2Go

The "real" SPARQL query is a string in SPARQL syntax. The method to use with SELECT queries is always model.sparqlSelect(String queryString). This method returns a QueryResultTable object, which is a ClosableIterable of QueryRow objects. QueryRow objects have two methods: getValue(String varname) and getLiteralValue(String varname), both return the values of variables bound by the SELECT statement.

[edit] examples

Selecting every resource which is tagged with tagJava:

		System.out.println("Query 1:");
		String queryString = "SELECT ?person WHERE { ?person <"+hasTag+"> "+tagJava.toSPARQL()+" }";
		QueryResultTable results = model.sparqlSelect(queryString);
		for(QueryRow row : results) {
			System.out.println(row);
		}

The basic concept of a SELECT query is given in the queryString

String queryString = "SELECT ?subject WHERE { ?subject ?predicate ?object }";

which would lead to a QueryResultTable returned by model.sparqlSelect(queryString) which contains "a subject per row" (try out!).

The real nature of those queryStrings cannot be explained here, you have to read the SPARQL docs for this purpose, it's not too hard to learn.

Now selecting resource and tag in every tagging statement:

		System.out.println("Query 2:");
		queryString = "SELECT ?resource ?tag WHERE { ?resource <"+hasTag+"> ?tag }";
		results = model.sparqlSelect(queryString);
		for(String var : results.getVariables()) {
			System.out.println(var);
		}
		for(QueryRow row : results) {
			System.out.println(row.getValue("resource") + " is tagged as " + row.getValue("tag"));
		}
[edit] The methods used
  • Node.toSPARQL is a method implemented in every node which can be used in SPARQL.
    • it serialises the node (here: tagJava) in the correct way.
    • SPARQL needs URIs in <>, Literals in "" and datatyped or language tagged literals have their own formats.
    • although you still need to know the SPARQL syntax, toSPARQL can be used if you don't know if you node is an URI or Literal.
    • in the example, tagJava could be a URI or a PlainLiteral, toSPARQL would create <> or "" depending on the node's type.
    • there is a reason for NOT using toSPARQL for the predicate (here: "<"+hasTag"+>")
      • because predicates are ALWAYS URIs, it's highly recommended to add the brackets manually here.
  • QueryResultTable.getVariables is a method to get all specified variables in the SELECT statement.
    • getVariables returns String[]{"person"} in the first query.
    • getVariables returns String[]{"resource","tag"} in the second query (maybe in a different order).

[edit] advanced SELECT queries

Selecting name of all resources with integer (typed) age of 19:

		System.out.println("Query 3:");
		queryString = "SELECT ?name WHERE { ?resource <"+hasAge+"> \"19\"^^<"+XSD._integer+"> . ?resource <"+hasName+"> ?name }";
		results = model.sparqlSelect(queryString);
		for(QueryRow row : results) {
			System.out.println(row);
		}

If we have declared

DatatypeLiteral nineteen = model.createDatatypeLiteral("19",XSD._integer);

we can also use toSPARQL here:

queryString2 = "SELECT ?name WHERE { ?resource <"+hasAge+"> "+nineteen.toSPARQL()+" . ?resource <"+hasName+"> ?name }";
assert queryString.equals(queryString2);

Even more complex SPARQL features can be used. E.g. FILTER with regex. Nothing outside the query string has to be changed.

Selecting name and age of all resources with a name like ".*? Völkel" (case-insensitive) with a regular expression (Regex)

		System.out.println("Query 4:");
		queryString = "SELECT ?name ?age WHERE { ?resource <"+hasName+"> ?name . FILTER regex(?name, \".*? Völkel\", \"i\") . ?resource <"+hasAge+"> ?age }";
		results = model.sparqlSelect(queryString);
		for(QueryRow row : results) {
			System.out.println(row);
		}
	}

}

(The 2 last closing brackets are for the main method and the class.)

[edit] Exceptions

  • (model.)sparqlSelect, sparqlConstruct and sparqlAsk throw MalformedQueryException if the SPARQL query is not well-formed.
  • the methods (model.)querySelect, queryConstruct throw a QueryLanguageNotSupportedException and also a MalformedQueryException

[edit] output

Query 1:
person:http://example.com/persons#konrad, 
person:http://example.com/persons#james, 
person:http://xam.de/foaf.rdf.xml#i, 
Query 2:
tag
resource
http://example.com/persons#guido is tagged as Python
http://example.com/persons#konrad is tagged as Python
http://example.com/persons#konrad is tagged as Java
http://example.com/persons#james is tagged as Java
http://xam.de/foaf.rdf.xml#i is tagged as Java
Query 3:
name:Konrad V, 
Query 4:
name:Max Völkel, age:29^^http://www.w3.org/2001/XMLSchema#integer, 

It's okay if your output contains something like

01.01.2007 12:34:56 org.ontoware.rdf2go.impl.jena24.ModelImplJena24 sparqlSelect
INFO: Query SELECT ?resource ?tag WHERE { ?resource <http://example.com/relations#hasTag> ?tag }

after every line "Query n:". It's omitted in this tutorial for readability.

Personal tools