Using Federation in AllegroGraph
In AllegroGraph, Federation is the composition of multiple triple-stores into a single virtual store. The composite store has access to all of the triples and features (e.g., reasoning) in its leaf stores and can contribute its own features as well. Federation is light-weight and flexible and makes it possible to build stores with capabilities that are difficult to achieve in other ways.
a Very Simple Example
We'll assume that you have successfully installed AllegroGraph. Let's start by putting Lisp into the correct package, making sure that enable-print-decoded to true so that it will be easier to see what we are doing, and enabling the !-reader so that it is easier to type.
(in-package #:db.agraph.user)
(enable-print-decoded t)
(enable-!-reader)
Now we will create two triple-stores and add some triples to each of them. The first triple-store will be named red-leaf and will store information about things that are red.
> (register-namespace "ex" "http://example.franz.com/"
:errorp nil)
"http://example.franz.com/"
> (create-triple-store "red-leaf")
#<db.agraph::triple-db /Users/gwking/red-leaf,
open @ #x1347e4ca>
> (add-triple !ex:macintosh !rdf:type !ex:Apple)
1
> (add-triple !ex:redDelicious !rdf:type !ex:Apple)
2
Our second triple-store will be named green-leaf and we'll use it to store information about things that are green.
> (create-triple-store "green-leaf")
#<db.agraph::triple-db /Users/gwking/green-leaf,
open @ #x135a9882>
> (add-triple !ex:grannySmith !rdf:type !ex:Apple)
1
> (add-triple !ex:kermitTheFrog !rdf:type !ex:Frog)
2
This division may work for a while but the day will come when we want to know about all of the different kinds of Apples. Federation lets us make a new virtual store. We create this using federate-triple-stores. This requires a name for the federated store and a list of the stores from which it will be composed.
> (federate-triple-stores "everything"
(list "red-leaf" "green-leaf"))
#<federated-triple-store everything 2 sub-stores @ #x1374e0a2>
federate-triple-stores
also sets *db*:
> *db*
#<federated-triple-store everything 2 sub-stores @ #x12f3ae82>
Lets check on the apples. First, how many triples do we have altogether:
> (triple-count)
4
Good. Let's query:
> (get-triples-list :o !ex:Apple)
(<macintosh type Apple default-graph>
<redDelicious type Apple default-graph>
<grannySmith type Apple default-graph>)
How about SPARQL?
> (sparql:run-sparql
"prefix ex: <http://example.franz.com/>
select ?s where { ?s ?p ex:Apple . }"
:results-format :lists)
(({macintosh}) ({redDelicious}) ({grannySmith}))
:select
(?s)
1
Great. A federated store acts almost exactly like a regular triple-store. Let's close these stores and more on to a more complex example.
> (close-all-triple-stores)
Federation and Reasoning
For our next example, we'll write a function named build-example-triple-stores
that creates two stores and adds some triples to them.
(defun build-example-triple-stores ()
(register-namespace "ex" "http://www.franz.com/example#"
:errorp nil)
(create-triple-store "ontology")
(add-triple !ex:SmallBlackDog !rdfs:subClassOf !ex:BlackDog)
(add-triple !ex:BlackDog !rdfs:subClassOf !ex:Dog)
(add-triple !ex:Dog !rdfs:subClassOf !ex:Mammal)
(add-triple !ex:Giraffe !rdfs:subClassOf !ex:Mammal)
(add-triple !ex:Lion !rdfs:subClassOf !ex:Mammal)
(add-triple !ex:Mammal !rdfs:subClassOf !ex:Animal)
(create-triple-store "facts")
(add-triple !ex:Abbey !rdf:type !ex:BlackDog))
and then execute it:
(build-example-triple-stores)
Now that we have two leaf stores, we can compose them in different ways. As an example, we'll build two different federated triple-stores with reasoning. In the first case, we'll wrap our facts in an RDFS++ reasoner and then federate the wrapped store and our ontology (see figure 1). In the second, we'll federate our facts and ontology and then wrap this with RDFS++ reasoning (see figure 2).
Federate ontology and RDFS++ facts
Here is a diagram of what we are building:
Here is the code:
;; wrap with reasoning
> (setf facts-with-reasoner
(apply-rdfs++-reasoner
:db (find-triple-store "facts")
:name "facts++"))
#<reasoning-triple-store
facts++,
inner #<triple-db /tmp/facts,
open @ #x12958e12> @
#x12ac943a>
;; federate
> (setf federated-1
(federate-triple-stores
"federated-1"
(list facts-with-reasoner "ontology")))
#<federated-triple-store federated-1
2 sub-stores @ #x12ad0d7a>
Add reasoning to a federation
As above, here is a diagram of what we are building:
> (setf federated-2
(apply-rdfs++-reasoner
:db (federate-triple-stores
"federated-2"
(list "facts" "ontology"))))
#<reasoning-triple-store
rdfs++-federated-2,
inner #<federated-triple-store
federated-2 2 sub-stores @ #x12ad7b42>
@ #x12adc712>
Asking questions
Suppose we want to know all of the different rdf:type
s of Abbey. Let's ask both of our federated triple-stores:
> (get-triples-list :s !ex:Abbey :p !rdf:type :db federated-1)
(<Abbey type BlackDog default-graph>)
> (get-triples-list :s !ex:Abbey :p !rdf:type :db federated-2)
(<Abbey type BlackDog default-graph>
<Abbey type Animal>
<Abbey type Mammal> <Abbey type Dog>)
Not surprisingly, only the triple-store that applies reasoning to all of the data (not just the facts) is able to correctly infer the additional types of Abbey.