gremlin-java –global filtering

135 views
Skip to first unread message

Rani Pinchuk

unread,
May 14, 2013, 10:56:52 AM5/14/13
to gremli...@googlegroups.com

Dear all,

I would like to ask if there is a way to define a filter globally. That is, for a Pipeline, or even for a graph (so for all Pipelines processed over that graph). The idea for such a global filter is that it will provide a way to work on a sub graph without changing the rest of the code (the other Pipelines). 

The rational for that is as follows:

Suppose you have a big graph of people who know each other. Each person has an age.

And suppose you have already created a nice application looking at the connections between the people.

But now, you need to see connections only between kids. How do you do that? You want to look at the very same graph, but filter all the adults from it.

Usually, you will need to go over all the pipelines in the application, and after to each step emitting vertices, add a step like .has(“age”, T.lt, 12)

But this can be a big work (which also ends up with not very elegant code) for quite a simple problem. Obviously, later you might want to look at other parts of the graph (e.g. all people in other ages, or with certain professions…).

I could not find if gremlin-java supports something like that and wonder if anyone has any suggestion.

Thanks,

Rani

Marko Rodriguez

unread,
May 14, 2013, 4:21:28 PM5/14/13
to gremli...@googlegroups.com
Hi,

You could make use of filter{} instead of has()?

filter(myClosure)

def myClosure = {
  // the definition to filter on
}

…where you predicate it updated in myClosure.

HTH,
Marko.
--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Rani Pinchuk

unread,
May 15, 2013, 1:58:05 AM5/15/13
to gremli...@googlegroups.com

Hi Marko,

There are few problems that will not be solved by this suggestion:

In the application I might just get all vertices with g.V(). So now I have to add a filter to these statements.

Also, such a filter has to be after each step emitting vertices, not only in the end of the path. For example if we are looking for the friends of the friends of someone, we will have something like:
.out(“knows”).out(“knows”).simplePath()
If we want it only for connections between kids, the following will not be enough:
.out(“knows”).out(“knows”).simplePath().has(“age”, T.lt, 12)
because a child can know an adult that knows another child that is not known to the first child. So the following path will be needed:
.has(“age”, T.lt, 12).out(“knows”).has(“age”, T.lt, 12).out(“knows”).simplePath().has(“age”, T.lt, 12)

In general, adding a filter (has(), or filter()) makes all the code very long and complex.

I am looking for something like:

g.setGlobalPipe(pipe.has(“age”, T.lt, 12))

that will filter all the vertices whenever the graph g is accessed.

Kind regards,

Rani

Daniel Kuppitz

unread,
May 15, 2013, 6:00:07 AM5/15/13
to gremli...@googlegroups.com
Hi Rani,

you can also use Gremlins user defined steps to keep your queries short.

Given a sample graph:

a = g.addVertex(['name':'A','age':10])
b = g.addVertex(['name':'B','age':11])
c = g.addVertex(['name':'C','age':12])
d = g.addVertex(['name':'D','age':13])

g.addEdge(a, b, 'knows')
g.addEdge(a, c, 'knows')
g.addEdge(b, c, 'knows')
g.addEdge(b, d, 'knows')

...and a user defined step:

Gremlin.defineStep('fof', [Vertex,Pipe], { closure ->
  pipe = _().out('knows')
  if (closure != null) {
    pipe = pipe.filter(closure)
  }
  pipe = pipe.out('knows')
  if (closure != null) {
    pipe = pipe.filter(closure)
  }
  pipe
})

...you can do this:

gremlin> a.fof().map()
==>{name=C, age=12}
==>{name=D, age=13}
gremlin> a.fof{ it.age < 13 }.map()
==>{name=C, age=12}
gremlin> a.fof{ it.age < 12 }.map()
gremlin>

As you can see, the filter is always applied to each fof-vertex, but you only have to write it once. Actually that's what Marko meant, he just didn't mention the user defined step that makes everything even shorter.

Cheers,
Daniel

Rani Pinchuk

unread,
May 15, 2013, 6:27:59 AM5/15/13
to gremli...@googlegroups.com
Hi Daniel,

I agree that I can use steps or other mechanisms in my code to have this capability in advance. The code still will not be as readable as it could - imagine that for each path you write in your code, you have to define a step. This is necessary as you want to have this filter globally, so each access to the graph should be filtered. Also it is even less elegant in Java - where the usage of step is not as elegant as in Groovy. 

But even if I adopt this approach, it still means that I have to design my application in advance to allow this feature. If I have already coded the application, I cannot easily apply such a global filter - so I will have to have a quite big renovation of the code, or, alternatively, copy the sub graph into a new graph (which can be as painful).

Kind regards,

Rani

Daniel Kuppitz

unread,
May 15, 2013, 7:04:06 AM5/15/13
to gremli...@googlegroups.com
Hm, you can do this kind of filtering in Faunus*. Question is, do you need it for realtime queries or for analytics? I'm not aware of anything that can do this in realtime.

* see "Reduce the size of the graph early in a job chain" in Faunus' Performance Tuning documentation

Cheers,
Daniel

Daniel Kuppitz

unread,
May 15, 2013, 7:23:08 AM5/15/13
to gremli...@googlegroups.com
I don't know how user defined steps are written Java. To complete the example, here's what Marko initially meant. Rewrite your queries (you only need to do that once) to accept a filter. Then pass any filter you want:

Assuming the sample graph from my previous example:

gremlin> myFilter = {true};        a.out('knows').filter(myFilter).out('knows').filter(myFilter).map()
==>{name=C, age=12}
==>{name=D, age=13}
gremlin> myFilter = {it.age < 13}; a.out('knows').filter(myFilter).out('knows').filter(myFilter).map()
==>{name=C, age=12}
gremlin> myFilter = {it.age < 12}; a.out('knows').filter(myFilter).out('knows').filter(myFilter).map()
gremlin>

This way you only need to pass a different filter function in Java.

Cheers,
Daniel
Reply all
Reply to author
Forward
0 new messages