Created
August 15, 2014 04:07
-
-
Save bollwyvl/6f29fb3830f7ca3ba7b1 to your computer and use it in GitHub Desktop.
Trike - Training Wheels for Triples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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