El código y los tests los podéis encontrar en mi repositorio de Github.
Usando Sesame como repositorio semántico. Describimos un grafo RDF:

 (def  *graph*
   (build-graph
     [(build-uri-node "http://test.com/whatever"
         [(build-relation :rdf "relation-1" (build-literal-node "testa1"))
          (build-relation :rdf "relation-2" (build-literal-node "testa2"))])
      (build-uri-node :rdf "test-subjectb"
         [(build-relation :rdf "relation-2" (build-blank-node "a" []))])])
 

El grafo que acabamos de describir es quivalente a los siguientes tripletes RDF (con notación turtle):

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
 <http://test.com/whatever> rdf:relation-1 "testa1" .
 <http://test.com/whatever> rdf:relation-2 "testa2" .
 rdf:test-subjectb rdf:relation-2 _:a .
 

El grafo que hemos guardado en *graph* podemos manipularlo en memoria, pero para almacenarlo, debemos obtener una conexión con un repositorio. Supongamos que tenemos una base de datos llamada "clojure_sesame", podemos usarla para almacenar el grafo en esa base de datos:

 (def *connection*
      (. (init-repository "com.mysql.jdbc.Driver" 
                          "jdbc:mysql://localhost:3306/clojure_sesame" 
                          "root" 
                          "root")
          getConnection)
 (write-graph-in-repository *graph* *connection*)
 

Una funcionalidad interesante es consultar un grafo RDF de una forma similar al uso que se hace de SQL para consultar un base de datos relacional.
Para dar solución a esta necesidad se ha estandarizado SPARQL (SPARQL Protocol and RDF Query Language) por parte de la W3C (http://www.w3.org/TR/rdf-sparql-query/).

La biblioteca ofrece esta funcionalidad mediante la construcción de plantillas: grafos RDF, donde se pueden insertar constructores para nodos variables y para relaciones variables:

 (def  *template*
   (build-graph-template 
      [{:template (build-graph
                            [(build-variable-node :x
                                 [(build-variable-relation :y 
                                      (build-variable-node :z []))])])
        :filters []}])]
 

La función (build-graph-template) acepta mapas con dos claves, :template que debe contener como valor un grafo con partes variables, y :filters, una colección de filtros que se pueden aplicar a los nodos variables. Por ejemplo:

 (build-filter :x "?x < 25")
 (build-filter :y "isURI(?y)")
 

También se pueden describir partes opcionales de la plantilla con la función (build-optional-graph).

Una vez que tenemos la plantilla debemos seleccionar que variables queremos que la consulta nos devuelva. En el ejemplo anterior, tenemos una plantilla con tres variables :x :y :z, si sólo nos interesan las variables :x e :y, construimos la consulta de la siguiente manera:

 (def *result*
   (query-template-in-repository
                              :x :y
                              *template*
                              *connection*)
 

La invocación anterior es equivalente a realizar la siguiente consulta SPARQL:

 SELECT ?x ?y WHERE { ?x ?y ?z .}
 

Los resultados se devuelven como colecciones de mapas, donde cada mapa contiene una solución para :x e :y:

 ;; El resultado de la consulta
  [{:y {:prefix "", :value "http://www.w3.org/1999/02/22-rdf-syntax-ns#relation-2"}
    :x {:prefix "", :value "http://test.com/test-subjecta/whatever"}}
   {:y {:prefix "", :value "http://www.w3.org/1999/02/22-rdf-syntax-ns#relation-1"}
    :x {:prefix "", :value "http://test.com/test-subjecta/whatever"}}
   {:y {:prefix "", :value "http://www.w3.org/1999/02/22-rdf-syntax-ns#relation-2"}
    :x {:prefix "", :value "http://www.w3.org/1999/02/22-rdf-syntax-ns#test-subjectb"}}]
 

Las plantillas no solo describen patrones para consultas SPARQL, sino que se pueden sustituir las partes variables de la plantilla, si queremos transformarla en un grafo de nuevo. Usando el primer resultado de la consulta, podemos hacer:

 (template-to-graph *template* (first *result*))
 

Y obtendríamos el grafo equivalente resolviendo :x e :y (en este caso todavía quedaría la parte variable referente a :z).

También podemos usar la capacidad de sustitución de las plantillas para dar valores parciales a variables al hacer una consulta:

 (query-template-in-repository
                            :x :y {:z (build-literal-node "testa1")}
                            *template*
                            *connection*)
 

De esta manera obtendríamos una consulta equivalente a:

 SELECT ?x ?y 
 WHERE { 
   ?x ?y "testa1" .
 }
 

Esta biblioteca, ofrece un acceso a RDF de bastante bajo nivel, manipulando tripletes de forma individual, pero puede servir de base para construir una capa de persistencia semántica para aplicaciones web, quizá construida sobre OWL, el lenguaje de descripción de ontologías de la W3C.