Link Search Menu Expand Document
Start for Free


This page discusses using Clojure to interact with Stardog.

Page Contents
  1. Overview
  2. Installation
  3. API Overview
  4. Examples
    1. Create a connection and run a query
    2. Insert data
    3. Run a query with a connection pool
    4. SPARQL Update
    5. Graph function for Construct queries
    6. Ask function for ASK queries


The stardog-clj source code is available under the Apache 2.0 license.

Stardog-clj provides a set of functions as API wrappers to the native SNARL API. These functions provide the basis for working with Stardog, starting with connection management, connection pooling, and the core parts of the API, such as executing a SPARQL query or adding and removing RDF from the Stardog database. Over time, other parts of the Stardog API will be appropriately wrapped with Clojure functions and idiomatic Clojure data structures.

Stardog-clj provides the following features:

  • Specification based descriptions for connections, and corresponding “connection” and “with-connection-pool” functions and macros.
  • Functions for query, ask, graph, and update to execute SELECT, ASK, CONSTRUCT, and SPARQL Update queries respectively.
  • Functions for insert and remove, for orchestrating the Adder and Remover APIs in SNARL.
  • Macros for resource handling, including with-connection-tx, with-connection-pool, and with-transaction.
  • Support for programming Stardog applications with either the connection pool or direct handling of the connection.
  • Idiomatic clojure handling of data structures, with converters that can be passed to query functions

The API with source docs can be found in the stardog.core and stardog.values namespaces.


Stardog-clj is available from Clojars. To use, just include the following dependency:

[stardog-clj "7.4.0"]

Starting with Stardog 6.0.1, the stardog-clj version always matches the latest release of Stardog.

API Overview

The API provides a natural progression of functions for interacting with Stardog

(create-db-spec "testdb" "http://localhost:5820/" "admin" "admin" "none")

This creates a connection space for use in connect or make-datasource with the potential parameters:

{:url "http://localhost:5820/" :db "testdb" :pass "admin" :user "admin" :max-idle 100 :max-pool 200 :min-pool 10 :reasoning false}

Create a single Connection using the database spec. Can be used with with-open, with-transaction, and with-connection-tx macros.

(connect db-spec)

Creates a data source, i.e. ConnectionPool, using the database spec. Best used within the with-connection-pool macro.

(make-datasource db-spec)

Executes the body with a transaction on each of the connections. Or establishes a connection and a transaction to execute the body within.

(with-transaction [connection...] body)
(with-connection-tx binding-forms body)

Evaluates body in the context of an active connection obtained from the connection pool.

(with-connection-pool [con pool] .. con, body ..)


Here are some examples of using stardog-clj:

Create a connection and run a query

=> (use 'stardog.core)
=> (def c (connect {:db "testdb" :url "snarl://localhost"}))
=> (def results (query c "select ?n { .... }"))
=> (take 5 results)
({:n #<StardogURI>} {:n #<StardogURI>} {:n #<StardogURI>} {:n #<StardogURI>} {:n #<StardogURI>})

=> (def string-results (query c "select ?n { .... }" {:converter str}))
=> (take 5 string-results)
({:n ""} {:n ""} {:n ""} {:n ""} {:n ""})

Insert data

(let [c (connect test-db-spec)]
               (with-transaction [c]
                 (insert! c ["urn:test" "urn:test:clj:prop2" "Hello World"])
                 (insert! c ["urn:test" "urn:test:clj:prop2" "Hello World2"]))

Run a query with a connection pool

myapp.core=> (use 'stardog.core)
myapp.core=> (def db-spec (create-db-spec "testdb" "snarl://localhost:5820/" "admin" "admin" "none"))
myapp.core=> (def ds (make-datasource db-spec))
myapp.core=> (with-connection-pool [conn ds]
        #_=>   (query conn "SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 2"))
({:s #<URI urn:test1>, :p #<URI urn:test:predicate>, :o "hello world"} {:s #<URI urn:test1>, :p #<URI urn:test:predicate>, :o "hello world2"})


;; First, add a triple
;; Then run an udpate query, which is its own transaction
;; Finally, confirm via ask
 (with-open [c (connect test-db-spec)]
               (with-transaction [c]
                 (insert! c ["urn:testUpdate:a1" "urn:testUpdate:b" "aloha world"]))
               (update c "DELETE { ?a ?b \"aloha world\" } INSERT { ?a ?b \"shalom world\" } WHERE { ?a ?b \"aloha world\"  }"
                         {:parameters {"?a" "urn:testUpdate:a1" "?b" "urn:testUpdate:b"}})
               (ask c "ask { ?s ?p \"shalom world\" }") => truthy)

Graph function for Construct queries

;; Graph results converted into Clojure data using the values methods
(with-open [c (connect test-db-spec)]
               (let [g (graph c "CONSTRUCT { <urn:test> ?p ?o } WHERE { <urn:test> ?p ?o } ")]
                 g) => (list [(as-uri "urn:test") (as-uri "urn:test:clj:prop3") "Hello World"]))

Ask function for ASK queries

;; Ask returns a Boolean
(with-open [c (connect test-db-spec)]
               (ask c "ask { ?s <> ?o }")) => truthy)