SPARQL is Resource Description Framework (RDF) query langauge. It allows to query triple stores and quad stores (called named graph).
Scheme Generic Tuple Store is work-in-progress Scheme Request For Implementation (SRFI) dubbed 168. It embeds a triple store or quad store or set of tuples of n items in Scheme programming language.
It rely on a pattern matching query semantic similar to SPARQL upon which minikanren logic language can be bound.
In the following, I will show how to translate some SPARQL queries into Scheme code.
In what follow we consider the following two stores. A triple store:
(define triplesotre (nstore #vu8(00) '(subject predicate object)))
And a quad store:
(define quadstore (nstore (#vu8 01) '(graph subject predicate object)))
And tx is a transaction object.
Data Types
The supported data types are composition of the follow basic Scheme types:
•
boolean
•
numbers (big integers, float and double)
•
symbol
•
string
•
bytevector
•
list (soon)
•
vector (soon)
There is no specific handling of date time objects or URIs.
Simple query
SPARQL
SELECT ?title
WHERE
{
<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title .
}
Scheme
(nstore-query
(nstore-from tx triplestore
(list 'http://example.org/book/book1
'http://purl.org/dc/elements/1.1/title
(nstore-var 'title))))
SPARQL
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE
{ ?x foaf:name ?name .
?x foaf:mbox ?mbox }
Scheme
(nstore-query (nstore-from tx triplestore
(list (nstore-var 'graph)
'http://xmlns.com/foaf/0.1/name
(nstore-var 'name)))
(nstore-where tx triplestore
(list (nstore-var 'graph)
'http://xmlns.com/foaf/0.1/mbox
(nstore-var 'mbox))))
If you prefer, you can define a procedure in Scheme:
(define (foaf symbol)
(string->symbol (string-append "http://xmlns.com/foaf/0.1/" (symbol->string symbol))))
And then the query becomes:
(nstore-query (nstore-from tx triplestore
(list (nstore-var 'graph)
(foaf 'name)
(nstore-var 'name)))
(nstore-where tx triplestore
(list (nstore-var 'graph)
(foaf 'mbox)
(nstore-var 'mbox))))
FILTER
SPARQL
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { ?x dc:title ?title
FILTER regex(?title, "^SPARQL")
}
Scheme
(gfilter (lambda (binding) (string-prefix? "SPARQL" (hashmap-ref binding 'title)))
(nstore-query (nstore-from tx triplestore
(list (nstore-var 'x)
'http://purl.org/dc/elements/1.1/title
(nstore-var 'title)))))
SPARQL
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX ns: <http://example.org/ns#>
SELECT ?title ?price
WHERE { ?x ns:price ?price .
FILTER (?price < 30.5)
?x dc:title ?title . }
Scheme
(gfilter (lambda (binding) (< (hashmap-ref binding 'price) 30.5))
(nstore-query (nstore-from tx triplestore
(list (nstore-var 'x)
'http://example.org/ns#price
(nstore-var 'price)))
(nstore-where tx triplestore
(list (nstore-var 'x)
'http://purl.org/dc/elements/1.1/title
(nstore-var 'title)))))
OPTIONAL
SPARQL
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name .
OPTIONAL { ?x foaf:mbox ?mbox }
}
Scheme
JOKER!
UNION
SPARQL
PREFIX dc10: <http://purl.org/dc/elements/1.0/>
PREFIX dc11: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { { ?book dc10:title ?title } UNION { ?book dc11:title ?title } }
Scheme
(gappend
(nstore-select (nstore-from tx triplestore
(list (nstore-var 'book)
'http://purl.org/dc/elements/1.0/title
(nstore-var 'title))))
(nstore-select (nstore-from tx triplestore
(list (nstore-var 'book)
'http://purl.org/dc/elements/1.1/title
(nstore-var 'title)))))
You are not obliged to copy-paste and you can factor queries...
FILTER NOT EXISTS
JOKER
FILTER EXISTS
JOKER
MINUS
JOKER
BIND
Use gmap
GROUP BY
JOKER
HAVING
Use gfilter
Sub-queries
Trivial.
Graph queries
Trivial.
ORDER BY
JOKER
DISTINCT
JOKER
LIMIT ... OFFSET ...
Use gtake and gdrop.