Skip to content
lvca edited this page Dec 22, 2012 · 3 revisions

Native Raw Graph Database API

<wiki:toc max_depth="4" />

Requirements

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

Introduction

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:

Use the database pool

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();
    }

First example

Create an empty database

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.

Create a graph of 1,000 vertexes

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"

Browse the entire 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

Build the graph

To build a graph you have to create vertexes and connect them with edges.

Create vertexes

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.

Create edges

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.

Manage labels

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" );

Remove edges

Use the database.removeEdge( edge ) to remove an edge between two vertexes.

Delete vertexes

On database.removeVertex( vertex ) method all the edges are unlinked before to delete the vertex. This assure the graph remains coherent.

Query the graph

OrientDB comes with a powerful query language based on SQL but with several extensions for graphs.

Query targets

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

Traversing

For more information look at Java Traverse.

== Right usage of the graph ==

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.

Polymorphism and custom types

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();

Concurrency

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
Clone this wiki locally