Detective Piotr Sparql lent back in his chair cradling a tumbler of vodka and reflected on his most recent case. It had started as a simple missing person; he’d been assigned to investigate the disappearance of Beatrice “Bee” Node:
@prefix foaf: <http://xmlns.com/foaf/0.1> .
</person/bnode> a foaf:Person;
foaf:name "Beatrice Node";
foaf:nick "Bee"
foaf:mbox <mailto:bnode@example.com>.
His investigation had started out routinely enough: trawling his usual sources to see if any of them had word of Bee’s location:
PREFIX geo <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX foaf <http://xmlns.com/foaf/0.1>
ASK WHERE {
{
</person/bnode>
geo:lat ?lat;
geo:long ?long.
}
UNION
{
?person
foaf:mbox <mailto:bnode@example.com>;
geo:lat ?lat;
geo:long ?long.
}
}
And then Bee turned up. Dead.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix foaf: <http://xmlns.com/foaf/0.1> .
@prefix bio: <http://purl.org/vocab/bio/0.1/> .
</person/bnode> a foaf:Person;
foaf:name "Beatrice Node";
bio:event [ a bio:Death;
bio:date "2008-01-29"^^xsd:date.
].
So he’d begun leaning on his sources harder, attempting to find those that had anything on Bee that might be useful in tracking down her murderer:
ASK WHERE {
{
</person/bnode> ?p ?o. }
UNION
{
?person
foaf:mbox <mailto:bnode@example.com>;
?p ?o.
}
}
…and then getting them to spill what they knew:
DESCRIBE </person/bnode>.
Pickings were slim. He tried a few obvious tacks:
PREFIX rel: <http://vocab.org/relationship/>
SELECT ?name ?mbox
WHERE {
?suspect rel:enemyOf </person/bnode>.
?suspect foaf:name ?name.
?suspect foaf:mbox ?mbox.
}
But Bee had had few enemies and all of them had alibis. He widened his search through the social networks:
PREFIX rel: <http://vocab.org/relationship/>
SELECT ?name, ?mbox
WHERE {
?suspect rel:enemyOf </person/bnode>.
?suspect foaf:knows ?otherSuspect.
?otherSuspect foaf:name ?name.
?otherSuspect foaf:mbox ?mbox.
}
But everyone’s alibis were water-tight. At this point he’d gone back to basics, gathering everything he could on the late lamented Bee Node. On a hunch he probed for more background on Bee’s social network. She’s been active in a number of forums and he’d figured that she may have unknowingly upset someone:
PREFIX sioc: <http://rdfs.org/sioc/ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
CONSTRUCT {
?suspect a foaf:Person;
?suspect foaf:name ?name;
?suspect foaf:mbox ?mbox.
}
WHERE {
{
?post a sioc:Post;
sioc:has_creator ?bee;
sioc:has_reply ?reply.
?bee sioc:email <mailto:bnode@example.com>.
?reply sioc:has_creator ?suspect.
?suspect sioc:name ?name;
sioc:email ?mbox.
}
UNION
{
?post a sioc:Post;
sioc:has_creator ?suspect;
sioc:has_reply ?reply.
?reply sioc:has_creator ?bee.
?bee sioc:email <mailto:bnode@example.com>.
?suspect sioc:name ?name;
sioc:email ?mbox.
}
}
Cross-referencing the email addresses on the short list of suspects, with data taken from a contact at nominet, he’d managed to gather some addresses:
PREFIX whois: <http://xml.nominet.org.uk/rdf/nom/domain#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX util: <http://www.example.org/sparql/util/>
SELECT
?name ?mbox ?line1 ?line2 ?postcode ?country
WHERE {
?suspect foaf:name ?name;
foaf:mbox ?mbox.
?d a whois:domainName;
whois:domainNameValue ?domainName;
whois:hasRegistrant ?registrant.
?registrant whois:registrantAddress ?address.
?address whois:addressline1 ?line1;
whois:addressline2 ?line2;
whois:postcode ?postcode;
whois:country ?country;
FILTER ( ?domainName = util:ExtractMailDomain(?mbox) )
}
ORDER BY ?name
The rest had come down to old fashioned legwork. He cursed himself softly as he finished his drink, pouring himself another slug of Absolut from the bottle in his desk drawer. In his haste he’d missed the obvious angles; hadn’t bothered to check out the family. after all they’d all seemed so…anonymous at first glance.
The murderer? Her relative: Uri. He’d been masquerading under an
alias.