Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries. Thanks for all your past and future contributions.

Tracker and QtSparql Basics

From Wiki
Jump to: navigation, search

This article provides an introduction to usage of Tracker RDF store on MeeGo 1.2 Harmattan platform beside the information available in QtSparql library documentation

Article Metadata
Tested with
Devices(s): Nokia N9/N950
Platform(s): MeeGo 1.2 Harmattan
Keywords: tracker, sparql, qtsparql, rdf
Created: conxt (20 Mar 2012)
Last edited: hamishwillee (13 Jun 2012)



Tracker is an RDF-based semantic data storage introduced to MeeGo 1.2 Harmattan to store user data including contacts, calendar entries and different system data. This article addresses those who had no previous experience with non-relational semantic data storage or SPARQL query language used to manipulate data in Tracker. The QtSparql documentation included in MeeGo 1.2 Harmattan API documentation shows some examples of data manipulation, however, it does not provide an introductory concept, neither it describes the differences between SPARQL features available in Tracker and W3C SPARQL standard.

Storage Concept

As opposed to relational databases, the data in Tracker in stored not in table form, but in form of a disconnected, directed graph. In queries the graph data is presented by its incidence list in form if triples:

subject predicate object

i.e. subject vertex is connected via predicate edge to object vertex in direction subject-to-object.

Subject is a resource. Every resource may have a URI or be a blank node (also called anonymous resource). A URI uniquely identifies the respective resource by reference, and anonymous resources cannot be indentified directly since they don't have a URI. An example of a URI is nco:Contact (a class name predefined in ontology) or something like urn:uuid:119d498b-73c1-72c5-67a9-345f29d00bba77fc

Predicate is always a URI reference limited by an RDF Vocabulary (ontology) used by a particular store. An example of a predicate is nco:extendedAddress. The description of Tracker ontology can be found here

Object can be a URI reference, a blank node or a literal. Literals represent actual human-readable data in form of strings. Thus, a whole data graph may be considered as a set of interrelations between literals, where literals are always terminal vertices of the graph, and the kind of interrelations is determined by predicates and the structure of the graph.

Data Extraction

The four statements SPARQL provides to extract data from an existing graph are SELECT, DESCRIBE, CONSTRUCT and ASK.

SELECT query, which is the most popular way to extract data, acts pretty much like SQL SELECT query, returning the table with number of columns being determined by the query.

To see what the SELECT statement can do, let's consider the following example:

SELECT ?fname ?sname ?tel ?nick WHERE {
 ?node a nco:Contact ;
nco:nameGiven ?fname ;
nco:nameFamily ?sname ;
nco:phoneNumber ?tel .
OPTIONAL { ?node nco:nickname ?nick }
ORDER BY ?fname ?sname

This query returns a table with ten or less rows (contacts). The columns of the table will contain First Name, Second Name, Telephone Number, and optionally, Nickname of the contacts. The rows are sorted by First Name (ascending order) and then Second Name (ascending order) and then the first 10 entries are returned.

The words that start with the question mark denote variables. Not all variables present in the query must be used for output and included in the SELECT statement. In the above example the variable ?node will always denote a resource, and, if included into the SELECT statement, will return URIs. This may be useful if we want to update some of the data later, but quite useless if the result of the query is used only for display.

The WHERE statement of the query is a set of condition triples (subject-predicate-object). The semicolon (;) at the end of a triple means that the next triple will share the same subject with the current triple and thus the subject will not need to be expressly stated once again. The dot (.) terminates this shortened syntax.

The predicates used in this query are:

  • a which is a syntactic sugar for rdf:type
  • nco:nameGiven
  • nco:nameFamily
  • nco:phoneNumber
  • nco:nickname

The question you may ask now is, where are the actual criteria the selection in made upon if the Tracker graph is huge?

  • The selected resources (?node) must be of nco:Contact type
  • The selected resources must have outgoing relations labeled nco:nameGiven, nco:nameFamily, and nco:phoneNumber, as none of them is marked as optional
  • The selected resources may have an outgoing relation labeled nco:nickname

The ASK queries are similar to the WHERE statement in SELECT query and return a Boolean value depending on whether there is at least one matching result.

The DESCRIBE queries return all the triples of the subgraph that has the identified resource or resources as a root.

The CONSTRUCT query returns all the triples of the new graph built with a provided template and based on data identified by its WHERE clause. For more information see the W3C SPARQL documentation.

Data Manipulation

To manipulate data within Tracker the SPARQL Update language is used since the original SPARQL contains only statements to extract data.

The queries used to manipulate data in Tracker are INSERT and DELETE queries. The other statements set by the W3C SPARQL Update recommendation are not supported.

Both queries are pretty mush similar in syntax with SELECT queries. Consider the two following examples:

 ?node nco:phoneNumber '+18005555555' ;
nco:nickname 'johndoe' . }
 ?node a nco:Contact ;
nco:nameGiven 'John' ;
nco:nameFamily 'Doe' .
 ?node a nco:Contact ;
nco:nameGiven 'John' ;
nco:nameFamily 'Doe' ;
nco:phoneNumber ?phone ;
nco:nickname ?nick .

The first query will find resource or resources with rdf:type of nco:Contact, nco:nameGiven of 'John' and nco:nameFamily of 'Doe' and add the nco:phoneNumber and nco:nickname properties with respective values.

The second query will find the same resources and delete them. Note the ?phone and ?nick variables not used elsewhere. It means that this query will delete the triples ?node nco:phoneNumber ?phone and ?node nco:nickname ?nick not caring about the values of the objects.

Some Peculiarities of SPARQL in Tracker and QtSparql

QtSparql variable binding

QtSparql provides variable binding syntax to facilitate the inclusion of literals into the queries. To use this syntax start the name of the variable with ?: or $:. Note that such variables are NOT the same “variables” of SPARQL – they are intended to be replaced with string values by QSparqlQuery::bindValue or QSparqlQuery::bindValues methods.

QtSparql does not support compound DELETE INSERT statements

In W3C SPARQL Update specification one can update properties with one DELETE INSERT statement. In QtSparql one must specify the StatementType of QSparqlQuery which cannot be InsertStatement and DeleteStatement at the same time.

In practice this means that you have to use two separate queries instead of one to update the information on the graph – even to change a value of a literal.

Tracker does not support unrestricted predicate variables

In W3C SPARQL Update you can delete all the information about a certain resource without knowing the structure of the information (like selecting everything with DESCRIBE query) by using a variable on the position of a predicate. In Tracker this is not allowed. If you try to use a predicate variable you will get the following error: “Tracker does not support unrestricted predicate variables”.

In practice this means that:

  • You have to use a DELETE WHERE query (see above)
  • You cannot delete the information being unaware of its structure


If you want to use QtSparql in your Qt project don't forget to include the following line into your .pro file:


and request the aegis credentials for your application:

<credential name="TrackerReadAccess" />
<credential name="TrackerWriteAccess" />
<credential name="GRP::metadata-users" />
This page was last modified on 13 June 2012, at 10:58.
41 page views in the last 30 days.