Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Created August 15, 2014 04:07
Show Gist options
  • Save bollwyvl/6f29fb3830f7ca3ba7b1 to your computer and use it in GitHub Desktop.
Save bollwyvl/6f29fb3830f7ca3ba7b1 to your computer and use it in GitHub Desktop.
Trike - Training Wheels for Triples
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"kernelspec": {
"codemirror_mode": {
"name": "python",
"version": 2
},
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"name": "",
"signature": "sha256:7545436b58570935c2a0fca05c72334cb3a3d1e371e62592e5da64b335ca1303"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Trike: training wheels for semantic queries\n",
"## An abuse of most of python's `__` functions for pithy semantic queries\n",
"- Be shorter than\n",
" - Raw SPARQL\n",
" - SurfRDF\n",
"- Fewer strings\n",
"- Better handling of Literals (remains to be seen)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from __future__ import unicode_literals\n",
"\n",
"import sys\n",
"import os\n",
"\n",
"from rdflib.plugins.stores.sparqlstore import SPARQLStore\n",
"from rdflib import Graph, ConjunctiveGraph, Namespace\n",
"from rdflib.namespace import (\n",
" RDF as rdf,\n",
" RDFS as rdfs,\n",
" FOAF as foaf\n",
")\n",
"\n",
"from jinja2 import Template\n",
"\n",
"from rdflib.term import Literal, URIRef"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use data from [LinkedMBD](http://linkedmdb.org)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"store = SPARQLStore(\"http://data.linkedmdb.org/sparql\", context_aware=False)\n",
"graph = Graph(store)\n",
"\n",
"movie = Namespace(\"http://data.linkedmdb.org/resource/movie/\")"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The classes."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class URITerm(object):\n",
" def __init__(self, uri):\n",
" self.uri = uri\n",
" \n",
" def __str__(self):\n",
" return \"<%s>\" % self.uri\n",
" \n",
"\n",
"class Variable(object):\n",
" def __init__(self, name):\n",
" self.name = name\n",
"\n",
" def __str__(self):\n",
" return \"?%s\" % self.name \n",
" \n",
" \n",
"class LiteralBinding(object):\n",
" _next_id = 0\n",
" \n",
" def __init__(self, literal, *args, **kwargs):\n",
" self.id = LiteralBinding.next_id()\n",
" self.literal = Literal(literal, *args, **kwargs)\n",
"\n",
" @classmethod\n",
" def next_id(cls):\n",
" cls._next_id += 1\n",
" return cls._next_id\n",
" \n",
" @property\n",
" def name(self):\n",
" return \"literal_%s\" % self.id\n",
" \n",
" def __str__(self):\n",
" #return \"?%s\" % self.name\n",
" return '\"%s\"' % self.literal\n",
"\n",
" \n",
"class Query(object):\n",
" def __init__(self, graph):\n",
" self._graph = graph\n",
" self._wheres = set()\n",
" self._variables = {}\n",
" self._literal_bindings = []\n",
"\n",
" self._template = Template(\"\"\"\n",
" SELECT {% for var in variables %}{{ var }} {% endfor %}\n",
" WHERE {\n",
" {% for subj, pred, obj in wheres %}\n",
" {{subj}} {{pred}} {{obj}} .\n",
" {% endfor %}}\n",
" \"\"\")\n",
" \n",
" def _query(self, bindings=None):\n",
" # What is the query string?\n",
" context = dict(\n",
" variables=bindings or self._variables.values(),\n",
" wheres=sorted(self._wheres)\n",
" )\n",
" return self._template.render(**context)\n",
" \n",
" def _term(self, term):\n",
" # What should I do with this term?\n",
" if isinstance(term, URIRef):\n",
" return URITerm(term)\n",
" elif isinstance(term, Variable):\n",
" return term\n",
" else:\n",
" term = LiteralBinding(Literal(term))\n",
" self._literal_bindings.append(term)\n",
" return term\n",
" \n",
" # MAGIC STUFF!\n",
" \n",
" def __getattr__(self, name):\n",
" return self._variables.setdefault(name, Variable(name))\n",
" \n",
" def __getitem__(self, sliced):\n",
" if isinstance(sliced, slice):\n",
" where = tuple([\n",
" self._term(term)\n",
" for term in (sliced.start, sliced.stop, sliced.step)\n",
" ])\n",
" self._wheres.add(where)\n",
" else:\n",
" return URIRef(sliced)\n",
" \n",
" def __call__(self, *args):\n",
" query = self._query(args)\n",
" \n",
" return self._graph.query(query)\n",
" \n",
" def __str__(self):\n",
" return self._query()\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 25
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we're ready to make a query! How about \n",
"> Who are all those actors that have worked with both Ridley Scott and George Lucas?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"q = Query(graph)\n",
"\n",
"q[q.actor : movie.actor_name : q.actor_name]\n",
"q[q.actor : movie.performance : q.george_movie_performance]\n",
"q[q.actor : movie.performance : q.ridley_movie_performance]\n",
"\n",
"q[q.george : movie.director_name : \"George Lucas\"]\n",
"q[q.ridley : movie.director_name : \"Ridley Scott\"]\n",
"\n",
"q[q.george_movie : movie.performance : q.george_movie_performance]\n",
"q[q.george_movie : movie.director : q.george]\n",
"q[q.george_movie : rdfs.label : q.george_movie_name]\n",
"\n",
"q[q.ridley_movie : movie.director : q.ridley]\n",
"q[q.ridley_movie : movie.performance : q.ridley_movie_performance]\n",
"q[q.ridley_movie : rdfs.label : q.ridley_movie_name]"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 41
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the end, we are just writing SPARQL (until something better comes along)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print str(q)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
" SELECT ?actor_name ?george_movie ?george_movie_name ?actor ?ridley_movie_performance ?george_movie_performance ?ridley_movie_name ?ridley_movie ?ridley ?george \n",
" WHERE {\n",
" \n",
" ?george <http://data.linkedmdb.org/resource/movie/director_name> \"George Lucas\" .\n",
" \n",
" ?actor <http://data.linkedmdb.org/resource/movie/actor_name> ?actor_name .\n",
" \n",
" ?actor <http://data.linkedmdb.org/resource/movie/performance> ?ridley_movie_performance .\n",
" \n",
" ?actor <http://data.linkedmdb.org/resource/movie/performance> ?george_movie_performance .\n",
" \n",
" ?ridley_movie <http://data.linkedmdb.org/resource/movie/performance> ?ridley_movie_performance .\n",
" \n",
" ?ridley_movie <http://data.linkedmdb.org/resource/movie/director> ?ridley .\n",
" \n",
" ?ridley_movie <http://www.w3.org/2000/01/rdf-schema#label> ?ridley_movie_name .\n",
" \n",
" ?george_movie <http://www.w3.org/2000/01/rdf-schema#label> ?george_movie_name .\n",
" \n",
" ?george_movie <http://data.linkedmdb.org/resource/movie/performance> ?george_movie_performance .\n",
" \n",
" ?george_movie <http://data.linkedmdb.org/resource/movie/director> ?george .\n",
" \n",
" ?ridley <http://data.linkedmdb.org/resource/movie/director_name> \"Ridley Scott\" .\n",
" }\n",
" \n"
]
}
],
"prompt_number": 51
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sweet, sweet results."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"results = q(q.actor_name, q.george_movie_name, q.ridley_movie_name)\n",
"for actor, movie1, movie2 in sorted(results):\n",
" print \"%s was in '%s' and '%s'\" % (actor, movie1, movie2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Ewan McGregor was in 'Star Wars Episode I: The Phantom Menace' and 'Black Hawk Down'\n",
"Ewan McGregor was in 'Star Wars Episode II: Attack of the Clones' and 'Black Hawk Down'\n",
"Ewan McGregor was in 'Star Wars Episode III: Revenge of the Sith' and 'Black Hawk Down'\n",
"Harrison Ford was in 'American Graffiti' and 'Blade Runner'\n",
"Harrison Ford was in 'Star Wars Episode IV: A New Hope' and 'Blade Runner'\n",
"Harrison Ford was in 'The Star Wars Holiday Special' and 'Blade Runner'\n",
"Liam Neeson was in 'Star Wars Episode I: The Phantom Menace' and 'Kingdom of Heaven'\n"
]
}
],
"prompt_number": 52
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment