Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

cali is a simple interface to databases supported by Gremlin — an amazing library for querying graph databases. See these presentations to see what I mean: 1, 2, 3. So far cali supports neo4j and TinkerGraph, though it's quite easy to to extend and develop cali further, to support any database that Gremlin/Pipes/Blueprints support.

cali is a single-threaded simple and dumb library for more or less simple queries. For multithreaded goodness see Nerlo.


  • Gremlin 0.5 Snapshot standalone package,

    Gremlin standalone resolves a host of dependencies for you: Gremlin, Pipes, Blueprints, neo4j

  • Erlang (with jinterface)

These are resolved through included maven project. If you don't want to build stuff yourself, there's a compiled package in the download section.

Starting cali

cali is implemented as an independent Java node:

java -classpath cali.jar com.dmitriid.cali.Main [OPTIONS]

where options are:

  • -n, name of the node. default is 'cali@localhost'
  • -m, name of the mailbox. default is 'mbox'
  • -c, cookie, if any. default is none
  • --connector, class of database connector to use. default is com.dmitriid.cali.db.Neo4JConnector

Of the four options above all are optional.

See com.dmitriid.cali.db.Neo4JConnector and com.dmitriid.cali.db.TinkerGraphConnector to see how to implement your own database connector

Your connector may require additional options, just append them to the options above (see example towards the end of this README).

Neo4JConnector options

  • -d, --db_path. path to neo4j database, required.

OrientDBConnector options

  • -u, --url. url of orientdb database, required.
  • --user. username, required.
  • --pass. password, required


Note: As of now RedisConnector doesn't support any additonal options such as host, ip, password or database. Support for these will come in the nerest future. Right now RedisConnector operates on database 0 on localhost on default port.


cali currently only has to ways to get and set data. These are... the get and the set methods. However, these are quite versatile in what they can do:

  • get Syntax: {get, WhatToRetrieve}

    WhatToRetrieve is any of the following:

    • {vertex, Id}
    • {vertex, Id, [ListOfPropertyNames]}, if you wish to retrieve several property values from a node
    • {edge, Id}
    • {q, Query}, if you want to run an ad-hoc Gremlin query

    These can also be passed in as a list:
    [{vertex, 1}, {edge, 2}, {vertex, 45, [name]}, {q, "$_/inE"}] etc.

  • set

    Syntax: {set, WhatToSet}

    WhatToSet is any of the following:

    • {vertex}, only create a vertex
    • {vertex, [Properties]}, a proplist of properties and their values
    • edge specifications, see "Setting edges" below

    These can also be passed as a list: [{vertex}, {vertex, [{name, "A vertex"}, {prop, "A prop"}]}]

Setting edges

In order to set an edge, you need to have incoming edges and outgoing edges. How do we get them? Well, using the get method, of course.

  • edge specs

    • {'<-', Label}, from vertex set on the right to the vertex set on the left, "incoming" edge
    • {'->', Label}, from vertex set on the left to the vertex set on the right, "outgoing" edge
    • {'<->', Label}, create both edges at once

Example. Setting edges

So here's how we can set a "knows" relationship between two nodes:

 {get, {vertex, 1}},
 {set, {'->', "knows"}},
 {get, {vertex, 2}}

Or vice versa:

 {get, {vertex, 1}},
 {set, {'<-', "is_known_by"}},
 {get, {vertex, 2}}

Or reciprocal:

 {get, {vertex, 1}},
 {set, {'<->', "friend_of"}},
 {get, {vertex, 2}}

Working with sets

Remember, we said that both get and set accept a list of things to retrieve/set? Well, it works for setting edges, as well:

Example. Banning several users at once

 {get, {q, "$_/outE/inV[@name='ban_list']"}},  %% retrieve the ban-list node
 {set, {'->', "contains"}},
       {vertex, 1234},    %% if we know the exact node id
       {q, "$_/outE/inV[@name='users']/outE/inV"}  %% we also decide to ban all users at once. Why can't we?

Regardless of the number of retrieved nodes in the second get call, there will be an edge labeled contains from vertex 1 to each of these nodes

This, of course, can easily be reversed:

       {vertex, 1234},    %% if we know the exact node id
       {q, "$_/outE/inV[@name='users']/outE/inV"}  %% we also decide to ban all users at once. Why can't we?
 {set, {'<-', "is_in"}},
 {get, {q, "$_/outE/inV[@name='ban_list']"}},  %% retrieve the ban-list node

Edges for newly created nodes

One cool thing about set is that it returns a set of newly created objects. So, if you want to create an edge while creating nodes [ {set, [{vertex}, {vertex}, {vertex}]}, {set, [{'<-', "in"}, {'->', "out"}]}, {set, [{vertex}, {vertex}, {vertex}]}, ]

More examples

So, let's fire it up and play with it:

$ java -classpath cali.jar com.dmitriid.cali.Main -d ~/Projects/java/neo4j/db
  .... or ... java -classpath cali.jar com.dmitriid.cali.Main --connector com.dmitriid.cali.db.TinkerGraphConnector
$ erl -sname client
erl> F = fun(Q) -> 
            {'mbox', 'cali@localhost'} ! {self(), Q},
              Any -> Any

erl> F([
         {get, {vertex, 0}},  %% the root. could've also done {q, "$_"}
         {set, {'->', "child"}},
         {set, {vertex, [{name, "Users"}]}},
         {set, {'->', "user"}},   %% yep, you can just go on and chain commands
                                  %% since every command returns a set of nodes it created/retrieved
         {set, [{vertex, [{name, "User1"}]},
                {vertex, [{name, "User2"}]},
                {vertex, [{name, "User3"}]}]}


erl> F([{get, {q, "$_/outE/inV[@name='Users']/outE/inV[@name='User1']"}}]).  %% get User1


erl> F([{get, {vertex, 3}}, {set, {'<->', "friend_of"}}, {get, {vertex, 4}}]).  %% set frendship information


erl> F([{get, {q, "$_/outE/inV[@name='Users']/outE/inV/@name"}}]).  %% get names of all users


erl> F([{get, [{vertex, 1}, {vertex, 3, [name]}]}]).  %% get only some properties for a node


erl> F([{get, [{vertex, 2, [name, id]}, {q, "$_/@id"}]}]).  %% get mixed results


erl> F(exit). %% shut the node down


As a result we will have a graph like this one:



an Erlang-Gremlin/Blueprints interface (neo4j/sail/etc...)







No releases published


No packages published