Wiki

Clone wiki

Telescope / SPARQLBuilder

Building SPARQL from Python expressions

Note: See the SPARQL sandbox for discussion of syntax ideas.

Get started with the following import, which grabs just Telescope's most widely used components.

>>> from telescope import *

This is equivalent to:

>>> from telescope.namespaces import RDF, RDFS, XSD, OWL, FN
>>> from telescope.sparql.expressions import Expression, and_, or_
>>> from telescope.sparql.queryforms import Ask, Construct, Describe, Select
>>> from telescope.sparql.helpers import is_a, v, op, fn, asc, desc, union, optional, Subject, Some

Variables

Telescope uses a Variable-Expression constructor to create variables that may be used in SPARQL comparisons, function calls, and conditionals. A Variable-Expression is simply an rdflib.Variable instance wrapped in an Expression. Because dealing with Variable-Expressions is so common, the Variable-Expression constructor is named v:

>>> v.name
Expression(?name)

>>> v.name == "Brian"
BinaryExpression(<built-in function eq>, Expression(?name), 'Brian')

>>> print (v.name == "Brian").compile()
?name = "Brian"

Building a simple SELECT

The Select class builds SELECT queries. Create a Select instance with a list of variables to project. These variables may be rdflib.Variable instances, Variable-Expressions, or variable name strings.

>>> query = Select([v.name])
>>> print query.compile()
SELECT ?name
WHERE { }

Adding patterns to the WHERE clause

Use the where method of Select to add patterns to the WHERE clause. It accepts any number of triples and graph patterns. Almost all methods of Select, including where, are generative, meaning they return a new Select instance.

>>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
>>> query = Select([v.name]).where((v.x, FOAF.name, v.name))
>>> print query.compile()
SELECT ?name
WHERE { ?x <http://xmlns.com/foaf/0.1/name> ?name }

Common subject patterns

Predicate-object lists are specified using slice syntax on the common subject:

>>> query = Select([v.name, v.mbox]).where(v.x[FOAF.name: v.name, FOAF.mbox: v.mbox])
>>> print query.compile()
SELECT ?name ?mbox
WHERE { ?x <http://xmlns.com/foaf/0.1/name> ?name ; <http://xmlns.com/foaf/0.1/mbox> ?mbox }

If the common subject is not a Variable-Expression, wrap it in the subject helper:

>>> from telescope.sparql.helpers import subject
>>> x = Variable('x')
>>> query = Select([v.name, v.mbox]).where(subject(x)[FOAF.name: v.name, FOAF.mbox: v.mbox])
>>> print query.compile()
SELECT ?name ?mbox
WHERE { ?x <http://xmlns.com/foaf/0.1/name> ?name ; <http://xmlns.com/foaf/0.1/mbox> ?mbox }

OPTIONAL graph patterns

Use the optional callable to wrap patterns in an OPTIONAL graph pattern:

>>> query = Select([v.name, v.mbox]).where((v.x, FOAF.name, v.name), optional((v.x, FOAF.mbox, v.mbox)))
>>> print query.compile()
SELECT ?name ?mbox
WHERE { ?x foaf:name <http://xmlns.com/foaf/0.1/name> .
        ?x OPTIONAL { ?x <http://xmlns.com/foaf/0.1/mbox> ?mbox } }

Alternatively, you may provide optional=True to the where call to put all arguments in an OPTIONAL graph pattern:

>>> query = Select([v.name, v.mbox]).where((v.x, FOAF.name, v.name)).where((v.x, FOAF.mbox, v.mbox), optional=True)

UNION graph patterns

Pass a union result to where to add alternative graph patterns. Each argument to union is treated as a sequence of patterns:

>>> query = Select([v.title]).where(union(
    [(v.book, DC10['title'], v.title)],
    [(v.book, DC11['title'], v.title)]
))
>>> print query.compile()
SELECT ?title
WHERE {
  { ?book <http://purl.org/dc/elements/1.0/title> ?title }
  UNION
  { ?book <http://purl.org/dc/elements/1.1/title> ?title }
}

Using PREFIX for namespaces

In the previous examples, full URIs (such as <http://xmlns.com/foaf/0.1/name>) were used in the WHERE clause. To use prefixes, pass a prefix mapping to compile:

>>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
>>> query = Select([v.name]).where((v.x, FOAF.name, v.name))
>>> print query.compile({FOAF: 'foaf'})
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }

Note: The Python sessions in the rest of this document may build upon previous sessions.

Adding FILTER constraints

Use the filter method of Select to add constraints. It accepts any number of expressions and keyword arguments (which are translated into binary expressions). Any constraints added in a single call to filter are combined as a single constraint using &&.

>>> query = query.filter(v.name == "Brian")
>>> print query.compile({FOAF: 'foaf'})
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name . FILTER (?name = "Brian") }

Using SPARQL operators in constraints

Telescope provides an operator constructor for the default SPARQL operators named op.

>>> query = query.filter(op.bound(v.name), ~op.isBlank(v.x))
>>> print query.compile({FOAF: 'foaf'})
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE {
  ?x foaf:name ?name .
  FILTER (?name = "Brian") .
  FILTER (bound(?name) && !isBlank(?x))
}

Telescope includes another operator constructor for the XPath Functions namespace named fn. To make an operator constructor for an arbitrary namespace, simply call op with the namespace:

>>> FUNC = Namespace('http://example.org/functions#')
>>> func = op(FUNC)
>>> print func.even(v.id).compile({FUNC: 'func'})
func:even(?id)

Updated