Comments:"Getting Started · thinkaurelius/titan Wiki · GitHub"
URL:https://github.com/thinkaurelius/titan/wiki/Getting-Started
The Graph of the Gods
The examples in this section make extensive use of a toy graph distributed with Titan called The Graph of the Gods. This graph is diagrammed below. The abstract data model is known as a property graph and this particular instance describes the relationships between the beings and places of the Roman pantheon. Moreover, special text and symbol modifiers in the diagram (e.g. bold, underline, etc.) denote different schematics/typings in the graph.
- key: a graph indexed key.
- key *: a graph indexed key that must have a unique value.
- key: a vertex-centric indexed key.
- hollow head edge: a functional/unique edge (no duplicates).
- tail crossed edge: a unidirectional edge (can only traverse in one direction).
Downloading Titan and Running the Gremlin Shell
Unbeknownst to the Gods, there still lived one Titan. This Titan can not be seen, has no name, and is only apparent in the fact that reality exists. Upon the shoulders of this lost Titan, all of reality hangs together in an undulating web of relations.Titan can be downloaded from the Downloads section of the project repository. Once retrieved and unpacked, a Gremlin terminal can be started. The Gremlin REPL (i.e. interactive shell) is distributed with Titan and differs slightly from the main TinkerPop Gremlin distribution in that is comes preloaded with Titan-specific imports
and helper methods. In the example below, titan.zip
is used, however, be sure to unzip the zip-file that was downloaded.
$ unzip titan.zip Archive: titan.zip creating: titan/ ... $ cd titan $ bin/gremlin.sh \,,,/ (o o) -----oOOo-(_)-oOOo----- gremlin>
The Gremlin terminal is a Groovy shell. Groovy is a superset of Java that has various shorthand notations that make interactive programming easier. Likewise Gremlin is a superset of Groovy with various shorthand notations that make graph traversals easy. The basic examples below demonstrate handling numbers, strings, and maps. The remainder of the tutorial will discuss graph-specific constructs.
gremlin> 100-10 ==>90 gremlin> "Titan:" + " The Rise of Big Graph Data" ==>Titan: The Rise of Big Graph Data gremlin> [name:'aurelius',vocation:['philosopher','emperor']] ==>name=aurelius ==>vocation=[philosopher, emperor]
NOTE: Please refer to GremlinDocs for a easy to use Gremlin reference.
Loading Data Into Titan
The example below will load The Graph of the Gods dataset diagrammed above into Titan. When working with a fresh graph (beyond this tutorial), TitanFactory
provides methods to create various Titan instances (e.g. local, distributed, etc.). A local, single machine instance of Titan is created using the TitanFactory.open(String directory)
method. Other pages in the documentation demonstrate distributing Titan across multiple machines, for instance using Cassandra or using HBase. Refer to the storage backend overview on how to choose the optimal persistence mode. For the purpose of this tutorial, a pre-constructed local graph is provided that is loaded with the above Graph of the Gods diagram.
gremlin> g = GraphOfTheGodsFactory.create('/tmp/titan') ==>titangraph[local:/tmp/titan]
The
GraphOfTheGodsFactory.create()
method does the following to the newly constructed graph prior to returning it:
Creates a collection of global and vertex-centric indices on the graph.
Adds all the vertices to the graph along with their properties.
Adds all the edges to the graph along with their properties.Please see the class source code:
https://github.com/thinkaurelius/titan/blob/master/titan-core/src/main/java/com/thinkaurelius/titan/example/GraphOfTheGodsFactory.java
For those using Titan/Cassandra (or Titan/HBase), be sure to make use of bin/cassandra-es.local
(or bin/hbase-es.local
) and GraphOfTheGodsFactory.load()
.
gremlin> g = TitanFactory.open('bin/cassandra-es.local') ==>titangraph[cassandrathrift:127.0.0.1] gremlin> GraphOfTheGodsFactory.load(g) ==>null
Global Graph Indices
The typical pattern for accessing data in a graph database is to first locate the entry point into the graph using a graph index. That entry point is an element (or set of elements) — i.e. a vertex or edge. From the entry elements, a Gremlin path description describes how to traverse to other elements in the graph via the explicit graph structure.
Given that there is a unique index on name
property, the Saturn vertex can be retrieved. The property map (i.e. the key/value pairs of Saturn) can then be examined. As demonstrated, the Saturn vertex has a name
of “saturn,” an age
of 10000, and a type
of “titan.” The grandchild of Saturn can be retrieved with a traversal that expresses: “Who is Saturn’s grandchild?” (the inverse of “father” is “child”). The result is Hercules.
gremlin> saturn = g.V('name','saturn').next() ==>v[4] gremlin> saturn.map() ==>name=saturn ==>age=10000 ==>type=titan gremlin> saturn.in('father').in('father').name ==>hercules
The property place
is also in a graph index. The property place
is an edge property. Therefore, Titan can index edges in a graph index. It is possible to query The Graph of the Gods for all events that have happened within 50 kilometers of Athens (latitude:37.97 and long:23.72). Then, given that information, which vertices were involved in those events.
gremlin> g.query().has('place',WITHIN,Geoshape.circle(37.97,23.72,50)).edges() ==>e[2T-o-2F0LaTPQBM][24-battled->40] ==>e[2R-o-2F0LaTPQBM][24-battled->36] gremlin> g.query().has('place',WITHIN,Geoshape.circle(37.97,23.72,50)).edges().collect { it.bothV.name.next(2) } ==>[hercules, hydra] ==>[hercules, nemean]
Graph indices are one type of index structure in Titan. Graph indices are accessible via the Graph.query()
method. The second aspect of indexing in Titan is known as vertex-centric indices. Vertex-centric indices are accessible via the Vertex.query()
method. Vertex-centric indices are described later.
Graph Traversal Examples
Hercules, son of Jupiter and Alcmene, bore super human strength. Hercules was a demigod because his father was a god and his mother was a human. Juno, wife of Jupiter, was furious with Jupiter’s infidelity. In revenge, she blinded Hercules with temporary insanity and caused him to kill his wife and children. To atone for the slaying, Hercules was ordered by the Oracle of Delphi to serve Eurystheus. Eurystheus appointed Hercules to 12 labors.In the previous section, it was demonstrated that Saturns’ grandchild was Hercules. This can be expressed using a loop
. In essence, Hercules is the vertex that is 2-steps away from Saturn along the in('father')
path.
gremlin> hercules = saturn.as('x').in('father').loop('x'){it.loops < 3}.next() ==>v[24]
Hercules is a demigod. To prove that Hercules is half human and half god, his parent’s origins must be examined. It is possible to traverse from the Hercules vertex to his mother and father. Finally, it is possible to determine the type
of each of them — yielding “god” and “human.”
gremlin> hercules.out('father','mother') ==>v[16] ==>v[28] gremlin> hercules.out('father','mother').name ==>jupiter ==>alcmene gremlin> hercules.out('father','mother').type ==>god ==>human gremlin> hercules.type ==>demigod
The examples thus far have been with respect to the genetic lines of the various actors in the Roman pantheon. The property graph data model is expressive enough to represent multiple types of things and relationships. In this way, The Graph of the Gods also identifies Hercules’ various heroic exploits - his famous 12 labors. In the previous section, it was discovered that Hercules was involved in two battles near Athens. It is possible to explore these events by traversing battled
edges out of the Hercules vertex.
gremlin> hercules.out('battled') ==>v[36] ==>v[40] ==>v[44] gremlin> hercules.out('battled').map ==>{name=nemean, type=monster} ==>{name=hydra, type=monster} ==>{name=cerberus, type=monster} gremlin> hercules.outE('battled').has('time',T.gt,1).inV.name ==>hydra ==>cerberus
The edge property time
on battled
edges is indexed by the vertex-centric indices of a vertex. Retrieving battled
edges incident to Hercules according to a constraint/filter on time
is faster than doing a linear scan of all edges and filtering (typically O(log n)
, where n
is the number incident edges). Gremlin is intelligent enough to use vertex-centric indices when available. A toString()
of a Gremlin expression shows the underlying query pipeline.
gremlin> hercules.outE('battled').has('time',T.gt,1).inV.name.toString() ==>[StartPipe, VertexQueryPipe(out,[battled],has,edge), IdentityPipe, InVertexPipe, PropertyPipe(name)]
More Complex Graph Traversal Examples
In the depths of Tartarus lives Pluto. His relationship with Hercules was strained by the fact that Hercules battled his pet, Cerberus. However, Hercules is his nephew — how should he make Hercules pay for his insolence?The Gremlin traversals below provide more examples over The Graph of the Gods. The explanation of each traversal is provided in the prior line as a //
comment.
Cohabiters of Tartarus
gremlin> pluto = g.V('name','pluto').next() ==>v[32] gremlin> // who are pluto's cohabitants? gremlin> pluto.out('lives').in('lives').name ==>pluto ==>cerberus gremlin> // pluto can't be his own cohabitant gremlin> pluto.out('lives').in('lives').except([pluto]).name ==>cerberus gremlin> pluto.as('x').out('lives').in('lives').except('x').name ==>cerberus
Pluto’s Brothers
gremlin> // where do pluto's brothers live? gremlin> pluto.out('brother').out('lives').name ==>sky ==>sea gremlin> // which brother lives in which place? gremlin> pluto.out('brother').as('god').out('lives').as('place').select ==>[god:v[16], place:v[8]] ==>[god:v[20], place:v[12]] gremlin> // what is the name of the brother and the name of the place? gremlin> pluto.out('brother').as('god').out('lives').as('place').select{it.name} ==>[god:jupiter, place:sky] ==>[god:neptune, place:sea]
Finally, Pluto lives in Tartarus because he shows no concern for death. His brothers, on the other hand, chose their locations based upon their love for certain qualities of those locations.
gremlin> pluto.outE('lives').reason ==>no fear of death gremlin> g.query().has('reason',CONTAINS,'loves').edges() ==>e[2B-g-2F0LaTPQBU][16-lives->8] ==>e[2H-k-2F0LaTPQBU][20-lives->12] gremlin> g.query().has('reason',CONTAINS,'loves').edges().collect{ [it.outV.name.next(),it.reason,it.inV.name.next()] } ==>[jupiter, loves fresh breezes, sky] ==>[neptune, loves waves, sea]
Next Steps
This section presented some basic examples of how to traverse The Graph of the Gods in Titan. In essence, a graph database is all about representing some world (structure) and traversing it to solve problems (process).
The remainder of this documentation discusses more in-depth examples and configurations for using Titan. Specifically,