SPARQL.Client
A SPARQL protocol client for Elixir.
Features
- Executes all forms of SPARQL queries against any SPARQL 1.0/1.1-compatible endpoint over HTTP.
- Supports result sets in both XML, JSON, CSV and TSV formats, with JSON being the preferred default for content-negotiation purposes.
- Supports graph results in any RDF serialization format understood by RDF.ex.
- Works with multiple HTTP client libraries.
Installation
The SPARQL.Client Hex package can be installed as usual, by adding sparql_client
to your list of dependencies in mix.exs
:
def deps do
[
{:sparql_client, "~> 0.1"}
]
end
Usage
The major function of the SPARQL.Client is SPARQL.Client.query/3
to perform the various forms of SPARQL queries. It takes a string with a SPARQL query, a URL of a SPARQL endpoint and some options. The query is only sent to the endpoint if it is syntactically valid. Depending on the query form either a SPARQL.Query.ResultSet
struct is returned or an RDF.Graph
.
For a more detailed description, including the various SPARQL.Client.query/3
options, see its documentation.
Examples
SELECT
query
# Places with free wi-fi from Wikidata
"""
SELECT ?item ?itemLabel (SAMPLE(?coord) AS ?coord)
WHERE {
?item wdt:P2848 wd:Q1543615 ; # wi-fi gratis
wdt:P625 ?coord .
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }
} GROUP BY ?item ?itemLabel
LIMIT 100
"""
|> SPARQL.Client.query("https://query.wikidata.org/bigdata/namespace/wdq/sparql")
SELECT
query results are returned as a SPARQL.Query.ResultSet
struct:
{:ok, %SPARQL.Query.ResultSet{
results: [
%SPARQL.Query.Result{
bindings: %{
"coord" => ~L"Point(23.32527778 42.695)",
"item" => ~I<http://www.wikidata.org/entity/Q5123174>,
"itemLabel" => ~L"City Garden"en
}
},
%SPARQL.Query.Result{
bindings: %{
"coord" => ~L"Point(24.74138889 42.13444444)",
"item" => ~I<http://www.wikidata.org/entity/Q7205164>,
"itemLabel" => ~L"Plovdiv Central railway station"en
}
},
%SPARQL.Query.Result{
bindings: %{
"coord" => ~L"Point(27.9122 43.1981)",
"item" => ~I<http://www.wikidata.org/entity/Q7916008>,
"itemLabel" => ~L"Varna railway station"en
}
},
%SPARQL.Query.Result{
bindings: %{
"coord" => ~L"Point(23.31966111 42.69133056)",
"item" => ~I<http://www.wikidata.org/entity/Q7937209>,
"itemLabel" => ~L"Vitosha Boulevard"en
}
},
...
],
variables: ["item", "itemLabel", "coord"]
}
}
ASK
query
"""
PREFIX : <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
ASK {:Sleepers dbo:starring :Kevin_Bacon }
"""
|> SPARQL.Client.query("http://dbpedia.org/sparql")
ASK
query results are also returned as a SPARQL.Query.ResultSet
struct, but with the results
field containing just the boolean result value.
{:ok, %SPARQL.Query.ResultSet{results: true, variables: nil}}
DESCRIBE
query
"DESCRIBE <http://dbpedia.org/resource/Elixir_(programming_language)>"
|> SPARQL.Client.query("http://dbpedia.org/sparql")
DESCRIBE
query results are returned as an RDF.Graph
resp. as an RDF.Dataset
if the format returned by the server supports quads.
{:ok, #RDF.Graph{name: nil
~I<http://dbpedia.org/resource/Elixir_(programming_language)>
~I<http://dbpedia.org/ontology/influenced>
~I<http://dbpedia.org/resource/LFE_(programming_language)>
~I<http://dbpedia.org/ontology/influencedBy>
~I<http://dbpedia.org/resource/Clojure>
~I<http://dbpedia.org/resource/Erlang_(programming_language)>
~I<http://dbpedia.org/resource/LFE_(programming_language)>
~I<http://dbpedia.org/resource/Ruby_(programming_language)>
~I<http://dbpedia.org/ontology/license>
~I<http://dbpedia.org/resource/Apache_License>
~I<http://dbpedia.org/property/creator>
~I<http://dbpedia.org/resource/José_Valim>
~I<http://dbpedia.org/property/platform>
~I<http://dbpedia.org/resource/Erlang_(programming_language)>
~I<http://purl.org/linguistics/gold/hypernym>
~I<http://dbpedia.org/resource/Language>
~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
~I<http://dbpedia.org/class/yago/Abstraction100002137>
~I<http://dbpedia.org/class/yago/ArtificialLanguage106894544>
~I<http://dbpedia.org/class/yago/Communication100033020>
~I<http://dbpedia.org/class/yago/Language106282651>
~I<http://dbpedia.org/class/yago/ProgrammingLanguage106898352>
~I<http://dbpedia.org/class/yago/WikicatProgrammingLanguages>
~I<http://dbpedia.org/class/yago/WikicatProgrammingLanguagesCreatedInThe2010s>
~I<http://dbpedia.org/ontology/Language>
~I<http://dbpedia.org/ontology/ProgrammingLanguage>
~I<http://schema.org/Language>
~I<http://www.w3.org/2002/07/owl#Thing>
~I<http://www.wikidata.org/entity/Q315>
~I<http://www.wikidata.org/entity/Q34770>
~I<http://www.wikidata.org/entity/Q9143>
~I<http://xmlns.com/foaf/0.1/homepage>
~I<http://elixir-lang.org>
~I<http://xmlns.com/foaf/0.1/name>
~L"Elixir"en
...
}
}
CONSTRUCT
query
"""
PREFIX : <http://example.org/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
CONSTRUCT {
:Elixir
:name ?name ;
:homepage ?homepage ;
:license ?license ;
:creator ?creator .
}
WHERE {
<http://dbpedia.org/resource/Elixir_(programming_language)>
foaf:name ?name ;
foaf:homepage ?homepage ;
dbp:creator ?creator ;
dbo:license ?license .
}
"""
|> SPARQL.Client.query("http://dbpedia.org/sparql")
CONSTRUCT
query results are also returned as an RDF.Graph
resp. as an RDF.Dataset
if the format returned by the server supports quads.
{:ok, #RDF.Graph{name: nil
~I<http://example.org/Elixir>
~I<http://example.org/creator>
~I<http://dbpedia.org/resource/José_Valim>
~I<http://example.org/homepage>
~I<http://elixir-lang.org>
~I<http://example.org/license>
~I<http://dbpedia.org/resource/Apache_License>
~I<http://example.org/name>
~L"Elixir"en}}
Configuration
SPARQL.Client uses Tesla, an abstraction over different HTTP client libraries. This allows you to use the HTTP client of your choice, as long as a Tesla adapter exists, currently httpc, hackney or ibrowse.
Without further configuration, the built-in Erlang httpc is used. For simple tests or if you want to keep your dependencies clean you can go with that, but I recommend using one of the alternatives. I’ve experienced encoding related issues with httpc, which none of the other HTTP clients had.
If you want to use another client library, you’ll have to add it to your list of dependencies in mix.exs
and configure Tesla to use it.
So, for hackney you’ll have to add hackney
to mix.exs
:
def deps do
[
{:sparql_client, "~> 0.1"},
{:hackney, "~> 1.6"}
]
end
and add this line to your config.exs
file (or environment specific configuration):
config :tesla, :adapter, :hackney
The ibrowse configuration looks similarly.
mix.exs
:
def deps do
[
{:sparql_client, "~> 0.1"},
{:ibrowse, "~> 4.2"}
]
end
config.exs
:
config :tesla, :adapter, :ibrowse
Getting help
Contributing
see CONTRIBUTING for details.
License and Copyright
(c) 2018 Marcel Otto. MIT Licensed, see LICENSE for details.