Learn

Explore development tutorials, how-tos and case studies

Starting to SPARQL with Twinkle

This short tutorial shows you how to start writing and running SPARQL queries using a simple SPARQL client called Twinkle. Twinkle is a free and simple java based SPARQL client (which also has a cool name). Twinkle has been developed by Leigh Dodds and you can read more about it here.

You can download the Twinkle binary from here. You will need to have Java 1.5 or higher installed to use Twinkle.

To install Twinkle:

  • Download the Zip file to a suitable folder on your computer.
  • Unzip the file contents.

To run Twinkle, open a command prompt and type:

java -jar twinkle.jar

To make it easier to run Twinkle in Microsoft Windows, you can create a simple command file, called for example twinkle.cmd, in the same folder as twinkle.jar that contains the command line above. Then just add the command file as a shortcut to your desktop and change the shortcut icon to something suitable (there just happens to be a nice star available).

Figure 1 - Twinkle Shortcut.

Figure 1 – Twinkle Shortcut.

Before you can use Twinkle to query specific SPARQL endpoints, you need to define them in Twinkle’s configuration file.

This is called config.n3 and you can find it at:

your_twinkle_install_folder\etc\config.n3

Lets add in the details for the Health Developer Network SPARQL endpoint so we can run some simple SPARQL queries against it.

Open config.n3 in a text editor (such as notepad on Microsoft Windows). Scroll down until you find the section commented as SPARQL ENDPOINT CONFIGURATION.

################################################################
# SPARQL ENDPOINT CONFIGURATION
#
# To configure new SPARQL endpoints you need to add the
# URI of the endpoint to this configuration file and indicate
# that the resource is of type "sources:Endpoint". This will
# ensure that the user interface displays the endpoint.
#
# Add an rdfs:label to label the endpoint in the UI. If there's
# no label then its won't display. The prefixes are automatically
# sorted based on the label.
#
# If the Endpoint requires a fixed data source and doesn't
# add this by default, its possible to set one here using
# the sources:defaultGraph property.
#
################################################################

You then need to add a new entry for the Health Developer Network SPARQL endpoint:

<https://data.developer.nhs.uk/sparql/> a sources:Endpoint
 ; rdfs:label "Health Developer Network".

Save your changes, exit the editor and start Twinkle. You should see something similar to figure 2.

Figure 2 - Twinkle.

Figure 2 – Twinkle.

To run a query against a SPARQL endpoint you need to first select it from the Remote Services listed. So click Health Developer Network, you will see that the title in the query window changes to show any queries run from this window will be run against Health Developer Network.

Figure 3 - Remote service selected.

Figure 3 – Remote service selected.

Lets now try a couple of simple SPARQL queries.

One of the first things I often do with a new RDF dataset, is to find out what predicates are used. To do this I run a SPARQL query that asks for all the distinct predicates in the dataset, ordered alphabetically:

select distinct ?p
{?s ?p ?o}
order by ?p

To run this query in Twinkle type it into the query window.

Figure 4 - Writing a query.

Figure 4 – Writing a query.

To run the query click the Run button. The query results are shown in the bottom of the query window.

Figure 5 - Query results in table format.

Figure 5 – Query results in table format.

If you click the text tab on results pane, you will see the returned results in text format. This is sometimes useful if you want to copy and paste results as text.

Figure 6 - Query results in text format.

Figure 6 – Query results in text format.

Lets now run a query to find out what is known about LEEDS TEACHING HOSPITALS NHS TRUST in the dataset. This has a URI of https://data.developer.nhs.uk/ods/org/RR8 and the query to find all the predicates and associated objects is:

select ?p ?o
{<https://data.developer.nhs.uk/ods/org/RR8> ?p ?o}

Which returns the results:

--------------------------------------------------------------------------------------------------------------------
| p                                                           | o                                                  |
====================================================================================================================
| <https://data.developer.nhs.uk/ods#name>                     | "LEEDS TEACHING HOSPITALS NHS TRUST"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods#addressLine1>             | "ST. JAMES'S UNIVERSITY HOSPITAL"^^<xsd:string>    |
| <https://data.developer.nhs.uk/ods#addressLine4>             | "LEEDS"^^<xsd:string>                              |
| <https://data.developer.nhs.uk/ods#addressLine2>             | "BECKETT STREET"^^<xsd:string>                     |
| <https://data.developer.nhs.uk/ods#nationalGrouping>         | <https://data.developer.nhs.uk/ods/org/Y51>         |
| <https://data.developer.nhs.uk/ods#addressLine5>             | "WEST YORKSHIRE"^^<xsd:string>                     |
| <https://data.developer.nhs.uk/ods#orgType>                  | <https://data.developer.nhs.uk/ods/ot/TR>           |
| <https://data.developer.nhs.uk/ods#openDate>                 | "1998-04-01"^^<xsd:date>                           |
| <https://data.developer.nhs.uk/ods#postcode>                 | "LS9 7TF"^^<xsd:string>                            |
| <https://data.developer.nhs.uk/ods#addressLine3>             | ""^^<xsd:string>                                   |
| <https://data.developer.nhs.uk/ods#gor>                      | <https://data.developer.nhs.uk/ods/org/D>           |
| <https://data.developer.nhs.uk/ods#highLevelHealthGeography> | <https://data.developer.nhs.uk/ods/org/Q32>         |
--------------------------------------------------------------------------------------------------------------------

Now for a more interesting query. Lets find out the names of all cardiology consultants in England. Cardiology specialty code has a URI of https://data.developer.nhs.uk/ods/specialtyCode/320 in the dataset and the query is:

PREFIX ods: <https://data.developer.nhs.uk/ods#>

select ?s ?surname ?initials
{?s ods:specialtyCode <https://data.developer.nhs.uk/ods/specialtyCode/320>.
 ?s ods:initials ?initials.
 ?s ods:surname ?surname.
}
order by ?surname

Which returns the results:

-------------------------------------------------------------------------------------------------------------
| s                                             | surname                               | initials          |
=============================================================================================================
| <https://data.developer.nhs.uk/ods/p/C4308506> | "Abraheem"^^<xsd:string>              | "A"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4039750> | "Achan"^^<xsd:string>                 | "V"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4025797> | "Adamson"^^<xsd:string>               | "D"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C2449197> | "Agarwal"^^<xsd:string>               | "A"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C5191127> | "Agarwal"^^<xsd:string>               | "S"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C3264407> | "Aggarwal"^^<xsd:string>              | "R"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4565611> | "Agrawal"^^<xsd:string>               | "S"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C2731531> | "Ahmad"^^<xsd:string>                 | "R"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C5196210> | "Ahmad"^^<xsd:string>                 | "I"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C3447055> | "Ahmed"^^<xsd:string>                 | "J"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C2731919> | "Ahsan"^^<xsd:string>                 | "A"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4019811> | "Aitchison"^^<xsd:string>             | "J"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C2363862> | "Akhtar"^^<xsd:string>                | "M"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C2634562> | "Al Mahdy"^^<xsd:string>              | "H"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C7068979> | "Al Sahli"^^<xsd:string>              | "W"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4238652> | "Al-Allaf"^^<xsd:string>              | "A"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C3389423> | "Al-Bustami"^^<xsd:string>            | "M"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C3538148> | "Al-Mohammad"^^<xsd:string>           | "A"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C4292830> | "Al-Obaidi"^^<xsd:string>             | "M"^^<xsd:string> |
| <https://data.developer.nhs.uk/ods/p/C6109904> | "Alam"^^<xsd:string>                  | "S"^^<xsd:string> |
...

There seems a lot of cardiology consultants in England, so to finish this tutorial lets see which of them are located at  LEEDS TEACHING HOSPITALS NHS TRUST by running the query:

PREFIX ods: <https://data.developer.nhs.uk/ods#>

select ?surname ?initials
{?s ods:specialtyCode <https://data.developer.nhs.uk/ods/specialtyCode/320>.
 ?s ods:locationOrg <https://data.developer.nhs.uk/ods/org/RR8>.
 ?s ods:initials ?initials.
 ?s ods:surname ?surname.
}
order by ?surname

Which returns the results:

---------------------------------------------------
| surname                     | initials          |
===================================================
| "Baig"^^<xsd:string>        | "M"^^<xsd:string> |
| "Ball"^^<xsd:string>        | "S"^^<xsd:string> |
| "Berkin"^^<xsd:string>      | "K"^^<xsd:string> |
| "Blackman"^^<xsd:string>    | "D"^^<xsd:string> |
| "Blaxill"^^<xsd:string>     | "J"^^<xsd:string> |
| "Cowan"^^<xsd:string>       | "J"^^<xsd:string> |
| "Dickinson"^^<xsd:string>   | "C"^^<xsd:string> |
| "Graham"^^<xsd:string>      | "L"^^<xsd:string> |
| "Hall"^^<xsd:string>        | "A"^^<xsd:string> |
| "Malkin"^^<xsd:string>      | "C"^^<xsd:string> |
| "McLenachan"^^<xsd:string>  | "J"^^<xsd:string> |
| "Pepper"^^<xsd:string>      | "C"^^<xsd:string> |
| "Reynolds"^^<xsd:string>    | "G"^^<xsd:string> |
| "Sapsford"^^<xsd:string>    | "R"^^<xsd:string> |
| "Schlosshan"^^<xsd:string>  | "A"^^<xsd:string> |
| "Scott"^^<xsd:string>       | "E"^^<xsd:string> |
| "Sivananthan"^^<xsd:string> | "U"^^<xsd:string> |
| "Tan"^^<xsd:string>         | "L"^^<xsd:string> |
| "Tayebjee"^^<xsd:string>    | "M"^^<xsd:string> |
| "Witte"^^<xsd:string>       | "K"^^<xsd:string> |
---------------------------------------------------