Skip to content

Sail Ouplementation

okram edited this page Jan 21, 2011 · 36 revisions

Sail is an RDF triple/quad store interface developed by OpenRDF. Any database the implements the Sail interfaces properly is a valid RDF triple/quad store. A graph database is a great way to build a triple/quad store because its possible to mix indexing and graph traversals to solve the RDF “pattern match” problem. To go from Graph to Sail, simply use GraphSail. GraphSail requires an IndexableGraph (e.g. TinkerGraph, Neo4jGraph, OrientGraph). The examples below use TinkerGraph and expose it as a GraphSail and thus, a Sail. While some basic examples are provided, please refer to the OpenRDF Sail documentation for a complete review of the framework.

NOTE ON TRANSACTIONS: Sail has its own transaction model that is different from the transaction model used by TransactionalGraph. GraphSail provides the user the flexibility of either using a TransactionalGraph in AUTOMATIC or MANUAL transaction mode. If a MANUAL transaction mode TransactionalGraph is used, then the Sail transaction semantics are as expected. If an AUTOMATIC transaction mode TransactionalGraph is used, then the Sail transaction semantics are ignored—in other words, its as if commit() and rollback() do nothing.

Basic Statement Handling

A statement in RDF is a triple or quad. The components of a statement are called: subject, predicate, object, and graph/context. The subject can be a URI or blank node. The predicate can only be a URI. The object can be a URI, blank node, or literal. Finally, the graph (or context) can be a URI or blank node.

Sail sail = new GraphSail(new TinkerGraph());
SailConnection sc = sail.getConnection();
ValueFactory vf = sail.getValueFactory();
sc.addStatement(vf.createURI("http://tinkerpop.com#1"), vf.createURI("http://tinkerpop.com#knows"), vf.createURI("http://tinkerpop.com#3"), vf.createURI("http://tinkerpop.com"));
sc.addStatement(vf.createURI("http://tinkerpop.com#1"), vf.createURI("http://tinkerpop.com#name"), vf.createLiteral("marko"), vf.createURI("http://tinkerpop.com"));
sc.addStatement(vf.createURI("http://tinkerpop.com#3"), vf.createURI("http://tinkerpop.com#name"), vf.createLiteral("josh"), vf.createURI("http://tinkerpop.com"));

System.out.println("get statements: ?s ?p ?o ?g");
CloseableIteration<? extends Statement, SailException> results = sc.getStatements(null, null, null, false);
while(results.hasNext()) {
    System.out.println(results.next());
}

System.out.println("\nget statements: http://tinkerpop.com#3 ?p ?o ?g");
results = sc.getStatements(vf.createURI("http://tinkerpop.com#3"), null, null, false);
while(results.hasNext()) {
    System.out.println(results.next());
}
get statements: ?s ?p ?o ?g
(http://tinkerpop.com#1, http://tinkerpop.com#knows, http://tinkerpop.com#3) [http://tinkerpop.com]
(http://tinkerpop.com#3, http://tinkerpop.com#name, "josh") [http://tinkerpop.com]
(http://tinkerpop.com#1, http://tinkerpop.com#name, "marko") [http://tinkerpop.com]

get statements: http://tinkerpop.com#3 ?p ?o ?g
(http://tinkerpop.com#3, http://tinkerpop.com#name, "josh") [http://tinkerpop.com]

Using SPARQL

SPARQL is the standard query language for RDF stores. OpenRDF provides a SPARQL query engine that can be used over any Sail. An example is provided below. Assume that the same statements from the previous example exist in the GraphSail below.

SPARQLParser parser = new SPARQLParser();
CloseableIteration<? extends BindingSet, QueryEvaluationException> sparqlResults;
String queryString = "SELECT ?x ?y WHERE { ?x <http://tinkerpop.com#knows> ?y }";
ParsedQuery query = parser.parseQuery(queryString, "http://tinkerPop.com");

System.out.println("\nSPARQL: " + queryString);
sparqlResults = sc.evaluate(query.getTupleExpr(), query.getDataset(), new EmptyBindingSet(), false);
while (sparqlResults.hasNext()) {
    System.out.println(sparqlResults.next());
}
SPARQL: SELECT ?x ?y WHERE { ?x <http://tinkerpop.com#knows> ?y }
[y=http://tinkerpop.com#3;x=http://tinkerpop.com#1]

Moving Between Sail and Graph

Its possible to get the Graph that is being modeled as a Sail and work from the Blueprints API perspective. In this way, its possible to leverage the tools provided for both Sail and Blueprints Graph.

Graph graph = ((GraphSail) sail).getGraph();
System.out.println();
for (Vertex v : graph.getVertices()) {
    System.out.println("------");
    System.out.println(v);
    for (String key : v.getPropertyKeys()) {
        System.out.println(key + "=" + v.getProperty(key));
    }
}
for (Edge e : graph.getEdges()) {
System.out.println("------");
System.out.println(e);
for (String key : e.getPropertyKeys()) {
    System.out.println(key + "=" + e.getProperty(key));
}
------
v[2]
value=U http://tinkerpop.com#3
------
v[1]
value=U http://tinkerpop.com#1
------
v[0]
value=urn:com.tinkerpop.blueprints.pgm.oupls.sail:namespaces
------
v[6]
value=P josh
------
v[4]
value=P marko
------
e[3][1-U http://tinkerpop.com#knows->2]
cp=U http://tinkerpop.com U http://tinkerpop.com#knows
c=U http://tinkerpop.com
p=U http://tinkerpop.com#knows
------
e[7][2-U http://tinkerpop.com#name->6]
cp=U http://tinkerpop.com U http://tinkerpop.com#name
c=U http://tinkerpop.com
p=U http://tinkerpop.com#name
------
e[5][1-U http://tinkerpop.com#name->4]
cp=U http://tinkerpop.com U http://tinkerpop.com#name
c=U http://tinkerpop.com
p=U http://tinkerpop.com#name
Clone this wiki locally