A SPARQL client for Elixir
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
integration_test
lib
test
.gitignore
.travis.yml
CHANGELOG.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
LICENSE.md
README.md
VERSION
mix.exs
mix.lock

README.md

SPARQL.Client

Travis Hex.pm

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.2"}
  ]
end

Usage

The major function of the SPARQL.Client is SPARQL.Client.query/3, which performs the various forms of SPARQL queries. It takes a SPARQL query string, a SPARQL endpoint URL, 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.Result struct or an RDF.Graph is returned.

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.Result struct:

{:ok, %SPARQL.Query.Result{
   results: [
     %{
         "coord" => ~L"Point(23.32527778 42.695)",
         "item" => ~I<http://www.wikidata.org/entity/Q5123174>,
         "itemLabel" => ~L"City Garden"en
     },
     %{
         "coord" => ~L"Point(24.74138889 42.13444444)",
         "item" => ~I<http://www.wikidata.org/entity/Q7205164>,
         "itemLabel" => ~L"Plovdiv Central railway station"en
     },
     %{
         "coord" => ~L"Point(27.9122 43.1981)",
         "item" => ~I<http://www.wikidata.org/entity/Q7916008>,
         "itemLabel" => ~L"Varna railway station"en
     },
     %{
         "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.Result struct, but with the results field containing just a boolean result value.

{:ok, %SPARQL.Query.Result{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 respective 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 respective 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. You can use it for simple tests or to keep your dependencies clean, 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, 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, Tesla.Adapter.Ibrowse

Getting help

Contributing

see CONTRIBUTING for details.

License and Copyright

(c) 2018 Marcel Otto. MIT Licensed, see LICENSE for details.