Semweb4j/filesQueries/step4
From semanticweb.org
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.
