Skip to content

User Defined Steps

okram edited this page Jan 10, 2011 · 37 revisions

Gremlin provides the ability for a user to define their own step definitions natively in Groovy or in Java. This is very useful when wishing to work with your low-level graph data at a higher level of abstraction. This section will discuss how to write your own step definitions and demonstrate how they are useful for making your Gremlin code more concise and more self-explanatory.

  1. Defining a Step in Gremlin
  2. Defining an Anonymous Step in Gremlin
  3. Defining a Step in Java

Defining a Step in Gremlin

Gremlin comes with a collection of built-in step definitions (see Gremlin Steps). It is possible for developers to create their own step definitions. Simply add a closure that represents the step to the respective classes.

c = {_{x = it}.outE[[label:'created']].inV.inE[[label:'created']].outV{x != it}}
[Iterable,Iterator,Vertex].each{it.metaClass.codeveloper = { Gremlin.compose(delegate, c()) }} 

In the code above, c is a closure to create the desired composite step and the second line is required to add c as the co_developer step. Given the graph diagrammed in Defining a Property Graph, we can determine the co-developers of a particular vertex.

gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).codeveloper
==>v[4]
==>v[6]

Realize that this step definition can be used like any other step definition.

gremlin> g.v(1).codeveloper.name
==>josh
==>peter

What step definitions allow you to do is to work with “higher order” relationships in your graph. Thus, instead of working at the level of

_{x = it}.outE[[label:'created']].inV.inE[[label:'created']].outV{x != it}

you can work at the more semantically natural level of

codeveloper

Defining an Anonymous Step in Gremlin

You can also create an anonymous step (or “lambda step”) using the step step. For example:

gremlin> g = TinkerGraphFactory.createTinkerGraph()    
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).outE.inV.step{ starts.next().map }
==>{name=vadas, age=27}
==>{name=lop, lang=java}
==>{name=josh, age=32}

The property starts is defined in Pipes and represents the previous pipe in the pipeline. For those familiar with Pipes, the provided step closure becomes the method AbstractPipe.processNextStart().

Defining a Step in Java

To ensure speed, it is possible to define steps in Java and then load the paths using import. Here is the previous co-developer path written in Java as a pipe (see Pipes).

public class CoDeveloperPipe extends Pipeline<Vertex,Vertex> {
  public CoDeveloperPipe() {
     List singleObjectList = new ArrayList() {
            public boolean add(Object object) {
                this.clear();
                super.add(object);
                return true;
            }
        };
     Pipe pipe0 = new AggregatorPipe(singleObjectList);
     Pipe pipe1 = new VertexEdgePipe(Step.OUT_EDGES);
     Pipe pipe2 = new LabelFilterPipe("created", Filter.NOT_EQUALS);
     Pipe pipe3 = new EdgeVertexPipe(Step.IN_VERTEX);
     Pipe pipe4 = new VertexEdgePipe(Step.IN_EDGES);
     Pipe pipe5 = new LabelFilterPipe("created", Filter.NOT_EQUALS);
     Pipe pipe6 = new EdgeVertexPipe(Step.OUT_VERTEX);
     Pipe pipe7 = new ObjectFilterPipe(pipe0.getSideEffect(), Filter.EQUALS);
     this.setPipes(pipe0, pipe1, pipe2, pipe3, pipe4, pipe5, pipe6, pipe7);
   }
}

Make sure that this class is in your Java classpath. If so, you can now include this newly created step/pipe in Gremlin.

[Iterable,Iterator,Vertex].each{ it.metaClass.codeveloper = {Gremlin.compose(delegate, new CoDeveloperPipe())}}