-
Notifications
You must be signed in to change notification settings - Fork 0
Graph Database Raw
<wiki:toc max_depth="4" />
To use the Graph Database interface you must include these jars in your classpath:
orient-commons-*.jar
orientdb-core-*.jar
If you're using the Graph Database interface connected to a remote server (not local/embedded mode) include also:
orientdb-client-*.jar
orientdb-enterprise-*.jar
OrientDB provides natively the class OGraphDatabase to handle graphs at document level. Furthermore, starting from v. 0.9.22, OrientDB provides an implementation of the Tinkerpop stack. You can use both APIs together.
Main graph classes:
- OGraphDatabase: Main class to handle graphs
In order to recycle database instance use the OGraphDatabasePool class. Remember to close ALWAYS the database instance when you've finished by using a try/finally block. Example:
database = OGraphDatabasePool.global().acquire("local:/tmp/graphdb", "admin", "admin");
try{
...
} finally{
database.close();
}
Launch the console and type:
> create database local:C:/temp/graph/graph admin admin local
If you're using Linux, MacOsX or any other Operative System change the location of the database to adhere to its file system.
This example creates a graph of 1,000 vertex. The root node will be bound to the database to get accessed for further uses (such as read). The graph has only one edge, so the deep level is of 1,000!
OGraphDatabase database = new OGraphDatabase("local:C:/temp/graph/graph");
database.open("admin", "admin");
ODocument rootNode = database.createVertex().field("id", 0);
ODocument currentNode = rootNode;
for (int i = 1; i < 1000; ++i) {
ODocument newNode = database.createVertex().field("id", i);
database.createEdge( currentNode, newNode);
currentNode = newNode;
}
database.setRoot("graph", rootNode);
database.close();
The main points of the code above are:
-
database.createVertex()
: creates a new vertex. Note vertexes and edges are always ODocument instances -
database.createVertex().field("id", 0)
: set the property "id" to the value 0 to the new created vertex object -
database.createEdge( currentNode, newNode)
: links the current node to the new one. OrientDB creates a new edge between them -
database.setRoot("graph", rootNode)
: set the root vertex as a root node called "graph"
public static void main(String[] args) {
OGraphDatabase database = new OGraphDatabase("local:C:/temp/graph/graph");
database.open("admin", "admin");
ODocument rootNode = database.getRoot("graph");
readAllTheGraph( rootNode );
database.setRoot("graph", rootNode);
}
private void readAllTheGraph(final ODocument iNode) {
for (ODocument edge: database.getOutEdges(iNode)) {
readAllTheGraph( database.getInVertex( edge ) );
}
}
The main points of the code above are:
-
database.getRoot("graph")
: get the root vertex by name ("graph") -
database.getOutEdges(iNode)
: browse all the outgoing edges -
database.getInVertex( edge )
: for each edge returns the incoming vertex
To build a graph you have to create vertexes and connect them with edges.
To create a new vertex:
ODocument vertex = database.createVertex();
vertex.field("type", "TV");
vertex.field("brand", "Samsung");
vertex.save();
To make the graph elements persistent, remember to call always the save() method against the new vertex.
Use the database.createEdge( sourceVertex, destinationVertex )
to create a new edge between two vertexes. name of the edge to use. Example:
ODocument vertex1 = database.createVertex();
vertex1.field("name", "Jay");
vertex1.field("surname", "Miner");
ODocument vertex2 = database.createVertex();
vertex2.field("name", "Amiga");
vertex2.field("type", "Computer");
ODocument edge = database.createEdge( vertex1, vertex2 );
edge.field("on", "1985");
edge.save();
Remember to call the save() method against the new edge or any of the vertexes connected. save() is viral and save recursively all the dirty elements.
TinkerPop Blueprints model supports the concept of "label". You can label vertexes and edges. In OrientDB a label is just a field as any others. To create an edge with a label you can use:
database.createEdge( vertex1, vertex2 ).field( "label", "ciao" );
Or you could use the constant:
database.createEdge( vertex1, vertex2 ).field( OGraphDatabase.LABEL, "ciao" );
Use the database.removeEdge( edge )
to remove an edge between two vertexes.
On database.removeVertex( vertex )
method all the edges are unlinked before to delete the vertex. This assure the graph remains coherent.
OrientDB comes with a powerful query language based on SQL but with several extensions for graphs.
Query can start from one or multiple root nodes. In SQL the queries can have as target only tables. In OrientDB you can use:
- the entire Class (the closest concept to a Relational Table). Example:
SELECT FROM v WHERE name = 'test'
- the entire Cluster (the physical place where records reside). Example:
select from cluster:OGraphVertex WHERE outEdges.size() > 0
- a single RID. Example:
select from 11:4
- multiple RIDs. Example:
select from [where outEdge.size() > 0
- sub-query as target:
SELECT FROM ( SELECT FROM v WHERE since IS NOT NULL) WHERE out.size() > 0
For more information look at Java Traverse.
OrientDB is a graph database. This means that traversing is very efficient. You can use this feature to optimize queries. A common technique is the Pivoting.
OrientDB supports the polymorphism with vertex and edges. You can create your own Vertex and Edge types using the Object Oriented paradigm.
All the vertex types must inherit the OGraphVertex at the highest point of the inheritance chain. The same is for edge types but the class to inherit is OGraphEdge. When you extends classes (or types, is the same concepts) you inherit all the fields and constraints of the extended class. Furthermore you can use the OrientDB query engine to execute polymorphic queries (see later).
Example of class inheritance schema:
OGraphVertex
|
Vehicle
|
/ \
/ \
Car Motocycle
This is the simple code that creates the classes:
OClass vehicleClass = database.createVertexType("GraphVehicle");
database.createVertexType("GraphCar", vehicleClass );
database.createVertexType("GraphMotocycle", vehicleClass );
Create vertexes of custom type:
ODocument carNode = database.createVertex("GraphCar").field("brand", "Hyundai").field("model", "Coupe").field("year", 2003).save();
ODocument motoNode = database.createVertex("GraphMotocycle").field("brand", "Yamaha").field("model", "X-City 250").field("year", 2009).save();
Execute polymorphic queries against custom types:
List<ODocument> result = database.query(new OSQLSynchQuery<ODocument>("select from GraphVehicle"));
Assert.assertEquals(result.size(), 2);
for (ODocument v : result) {
Assert.assertTrue(v.getSchemaClass().isSubClassOf(vehicleClass));
}
database.close();
Since release 1.2.0 concurrent accesses to the same graph are managed using different locking strategies: cb215cdf5dcad5ef23b05a9b716ffcac
By default DATABASE_LEVEL_LOCKING
is used. In case of single-thread massive insertion you can disable it:
79fb9ffb68fc5c6b8cb3a0c98833e9d5
NOTE: Set the locking mode after the database has been open or created.
Using the LOCK_MODE.RECORD_LEVEL_LOCKING
you have more fine-grained access to the graph locking only the portions you access, but this could raise dead-locks (the timeout expires, so no stall for the application) because multiple resources need to be locked, for example, when you remove an edge.
To avoid to incur into the dire http://code.google.com/p/orient/wiki/TroubleshootingJava#OConcurrentModificationException:Cannot_update_record#X:Y_in_s OConcurrentModificationException you have to:
- use the default
DATABASE_LEVEL_LOCKING
locking mode - disable caches. Level1 should be enough if you don't have multiple clients accessing to the remote protocol against the same server, otherwise disable the 2nd level cache as well
- always refer to the vertices and edges by their RID, never as document instances. The document instances you've in the current thread could be old because another client/thread could have updated them