SPARQL Inference – examples
Examples use a small, simple data set loosely based on the examples in "Semantic Web for the Working Ontologist" by Dean Allemang and James Hendler.
Examples assume the following prefixes:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX prod: <http://example.com/products/> PREFIX ex: <http://example.com/>
The data is about products in a clothing factory.
These examples can be run from Query Console, in SPARQL Update mode. SPARQL query results are shown here in JSON format, for convenience.
Overview
In this exercise we create a graph and insert triples about some products, one of which is a Henley. At this point, we know that a Henley is a shirt, but the database doesn't – so when we ask about shirts, the Henley isn't included in the results.
Then we set up inferencing. First insert some ontology data (a triple that tells us that Henley is a subclass of Shirts), then create a store (which tells the server how to interpret the ontology data). Then we pass the store into the query, and now the Henley does appear in the results.
Next we tell the server that the store we created should be used by default, so we can run the query without specifying a store.
- Set-up: graph and data
- Find all blue shirts – without inference
- Setup RDFS inferencing – insert some ontology data, create a store, run a query using the store
- Set some ruleset as default
- Use more than one ruleset
- Define your own ruleset
Example 1 (SPARQL Update):
## reset: ## drop the graph used in this exercise ## use "SILENT" so it doesn't give an error if the graph doesn't exist DROP SILENT GRAPH <http://marklogic.com/semantics/sb/products/inf-1> ;
Example 2 (SPARQL Update):
## create <http://marklogic.com/semantics/sb/products/inf-1> CREATE GRAPH <http://marklogic.com/semantics/sb/products/inf-1> ;
Example 3 (SPARQL Update):
## insert some triples into < http://marklogic.com/semantics/sb/products/inf-1> ## prod:1001 is a blue Henley ## prod:1002 is a blue shirt INSERT DATA { GRAPH <graph-1> { prod:1001 rdf:type ex:Henley ; ex:color "blue" . prod:1002 rdf:type ex:Shirt ; ex:color "blue" . } }
Example 1 (SPARQL Query):
SELECT ?product FROM <http://marklogic.com/semantics/sb/products/inf-1> WHERE { ?product rdf:type ex:Shirt ; ex:color "blue" } => [ { "product": "<http://example.com/products/1002>" } ]
Example 1 (SPARQL Update):
## insert some ontology data into <http://marklogic.com/semantics/sb/products/inf- 1> INSERT DATA { GRAPH <http://marklogic.com/semantics/sb/products/inf-1> { ex:Henley rdfs:subClassOf ex:Shirt . } } => Empty
Example 2 (XQuery):
(: create a store that uses the RDFS ruleset for inferencing :) let $rdfs-store := sem:ruleset-store("rdfs.rules",sem:store() ) return (: use the store you just created - pass it in to sem:sparql() :) sem:sparql(' PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX prod: <http://example.com/products/> PREFIX ex: <http://example.com/> SELECT ?product FROM <http://marklogic.com/semantics/sb/products/inf-1> WHERE { ?product rdf:type ex:Shirt ; ex:color "blue" }', (), (), $rdfs-store ) => [ { "product": "<http://example.com/products/1001>" }, { "product": "<http://example.com/products/1002>" } ]
Example 1 (XQuery):
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; (: Set the default ruleset for the database "Documents" to "rdfs.rules" Note: other ways to do this: * in the Admin UI, click on database "Documents”, scroll down to "default rulesets" on the left-hand side * use the REST management API - see [http://localhost:8002]/manage/v2/databases/Documents/properties :) let $config := admin:get-configuration() let $dbid := admin:database-get-id($config, "Documents") let $rules := admin:database-ruleset("rdfs.rules") let $new-config := admin:database-add-default-ruleset($config, $dbid, $rules) return admin:save-configuration($new-config)
Example 2 (XQuery):
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; (: Get the default ruleset(s) for the database "Documents" to verify you’ve set the default ruleset correctly. Note: other ways to do this: * in the Admin UI, click on database "Documents", scroll down to "default rulesets" on the left-hand side * use the REST management API - see [http://localhost:8002]/manage/v2/databases/Documents/properties :) let $config := admin:get-configuration() let $dbid := admin:database-get-id($config, "Documents") let $rules := admin:database-ruleset("rdfs.rules") let $db-rulesets := admin:database-get-default-rulesets($config, $dbid) return $db-rulesets => <ruleset xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns="http://marklogic.com/xdmp/database"> <location>rdfs.rules</location> </ruleset>
Example 3 (SPARQL query):
## re-run "find all blue shirts" – uses default ruleset SELECT ?product FROM <http://marklogic.com/semantics/sb/products/inf-1> WHERE { ?product rdf:type ex:Shirt ; ex:color "blue" } => [ { "product": "<http://example.com/products/1001>" }, { "product": "<http://example.com/products/1002>" } ]
Example 1 (XQuery):
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; (: Delete all the default rulesets for the database "Documents" before you start Note: other ways to do this: * in the Admin UI, click on database "Documents", scroll down to "default rulesets" on the left-hand side * use the REST management API - see [http://localhost:8002]/manage/v2/databases/Documents/properties :) let $config := admin:get-configuration() let $dbid := admin:database-get-id($config, "Documents") let $rules := admin:database-ruleset("rdfs.rules") let $db-rulesets := admin:database-get-default-rulesets($config, $dbid) let $new-config := admin:database-delete-default-ruleset($config, $dbid, $dbrulesets) return admin:save-configuration($new-config)
Example 2 (SPARQL Update):
## insert another triple into http://marklogic.com/semantics/sb/products/inf-1 ## prod:1003 is a Henley that has hue "blue" INSERT DATA { GRAPH <http://marklogic.com/semantics/sb/products/inf-1> { prod:1003 rdf:type ex:Henley ; ex:hue "blue" . } }
Example 3 (SPARQL Update):
## insert some more ontology data into http://marklogic.com/semantics/sb/products/inf-1 ## the predicate ex:color is equivalent to the predicate ex:hue INSERT DATA { GRAPH <http://marklogic.com/semantics/sb/products/inf-1> { ex:color owl:equivalentProperty ex:hue . } }
Example 4 (XQuery):
(: SPARQL query using 2 rulesets, RDFS and owl:equivalentProperty You could also do it this way: * set the default rulesets for the database to RDFS and owl:equivalentProperty; * query using SPARQL Query from query console or REST endpoint :) (: create a store that uses the RDFS and owl:equivalentProperty rulesets for inferencing :) let $rdfs-store := sem:ruleset-store( ("rdfs.rules", "equivalentProperty.rules"), sem:store() ) return (: use the store you just created - pass it into sem:sparql() :) sem:sparql(' PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX prod: <http://example.com/products/> PREFIX ex: <http://example.com/> SELECT ?product FROM <http://marklogic.com/semantics/sb/products/inf-1> WHERE { ?product rdf:type ex:Shirt ; ex:color "blue" }', (), (), $rdfs-store ) => [ { "product": "<http://example.com/products/1001>" }, { "product": "<http://example.com/products/1002>" }, { "product": "<http://example.com/products/1003>" } ]
This example draws from the geonames ontology and data sets – see http://www.geonames.org/ontology/documentation.html.
Example 1 (SPARQL Update):
## drop the customers graph DROP SILENT GRAPH <http://marklogic.com/semantics/sb/customers/inf-1> ;
Example 2 (SPARQL Update):
## create the customers graph CREATE GRAPH <http://marklogic.com/semantics/sb/customers/inf-1> ;
Example 3 (SPARQL Update):
## insert some triples from geonames ## * "Greater London" has parentFeature "England" PREFIX gn: <http://www.geonames.org/ontology#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> INSERT DATA { GRAPH <http://marklogic.com/semantics/sb/customers/inf-1> { <http://sws.geonames.org/2648110/> rdfs:isA gn:Feature ; rdfs:isDefinedBy <http://sws.geonames.org/2648110/about.rdf> ; gn:name "Greater London" ; gn:parentFeature <http://sws.geonames.org/6269131/> . <http://sws.geonames.org/6269131/> rdfs:isA gn:Feature ; rdfs:isDefinedBy <http://sws.geonames.org/2648110/about.rdf> ; gn:name "England" ; gn:parentFeature <http://sws.geonames.org/6269131/> . } }
Example 4 (SPARQL Query):
## check that the inserts into the customer graph worked SELECT * FROM <http://marklogic.com/semantics/sb/customers/inf-1> WHERE { ?s ?p ?o } ORDER BY ?s
Example 5 (XQuery):
(: create a rules file and insert it into the Schemas database :) (: Note: run this from Query Console with "Content Source" set to "Schemas" :) xdmp:document-insert( '/rules/livesin.rules', text { '# my rules for inference prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> prefix ex: <http://example.com/> prefix gn: <http://www.geonames.org/ontology#> rule "lives in" construct { ?person ex:livesIn ?place2 } { ?person ex:livesIn ?place1 . ?place1 gn:parentFeature ?place2 }' } )
Example 6 (SPARQL Query):
## find places that John Smith lives in – without inferencing PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX gn: <http://www.geonames.org/ontology#> PREFIX ex: <http://example.com/> SELECT ?person ?placeName FROM <http://marklogic.com/semantics/sb/customers/inf-1> WHERE { ?person ex:livesIn ?place . ?place gn:name ?placeName } => <http://marklogic.com/semantics/sb/customers/inf-1#JohnSmith> "Greater London"
Example 7 (XQuery):
(: find places that John Smith lives in – with inferencing, using my ruleset :) (: MarkLogic will look in the Config directory AND Schemas database for the named ruleset :) let $my-store := sem:ruleset-store("/rules/livesin.rules",sem:store() ) return (: use the store you just created - pass it in to sem:sparql() :) sem:sparql(' PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX gn: <http://www.geonames.org/ontology#> PREFIX ex: <http://example.com/> SELECT ?person ?placeName FROM <http://marklogic.com/semantics/sb/customers/inf-1> WHERE { ?person ex:livesIn ?place . ?place gn:name ?placeName } ORDER BY ?person', (), (), $my-store ) => <http://marklogic.com/semantics/sb/customers/inf-1#JohnSmith> "Greater London" <http://marklogic.com/semantics/sb/customers/inf-1#JohnSmith> "England"
Note: In MarkLogic 8 you can set the default ruleset for inferencing, so in Query Console you can run a SPARQL Query (not an XQuery) that makes use of inferencing. You can also run SPARQL over REST – using the SPARQL endpoint – and you’ll get automatic inferencing by way of the database’s default ruleset.
Example 8 (JavaScript):
// call sem.sparql from Server-side JavaScript var myStore = sem.rulesetStore("/rules/livesin.rules",sem.store() ) var query = " \ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \ PREFIX gn: <http://www.geonames.org/ontology#> \ PREFIX ex: <http://example.com/> \ \ SELECT ?person ?placeName \ FROM <http://marklogic.com/semantics/sb/customers/inf-1> \ WHERE \ { \ ?person ex:livesIn ?place . \ ?place gn:name ?placeName \ }" sem.sparql( query, [], [], myStore ) => <http://marklogic.com/semantics/sb/customers/inf-1#JohnSmith> "Greater London" <http://marklogic.com/semantics/sb/customers/inf-1#JohnSmith> "England"