Search code examples
gremlintinkerpop3

Is there a way for creating two zipped gremlin iterators with one advanced one position ahead?


I am trying to programmatically add edges to the graph.

The idea is that, I will zip two stream of vertices and if consecutive two meets some conditions, I will create an edge between them.

The problem is with the zipping though. I can't make it to zip two streams, with one stream advanced one position ahead.

(
    g.V().hasLabel("person").
    order().by("age")
    .as("x")
    .local(
        union(
            select("x"),
            select("x") // .skip(1)
        ).fold()
    )
)

==>[v[2],v[2]]
==>[v[1],v[1]]
==>[v[4],v[4]]
==>[v[6],v[6]]

The above works. But when I uncomment the skip part, I get

==>[v[2]]
==>[v[1]]
==>[v[4]]
==>[v[6]]

but I need:

==>[v[2],v[1]]
==>[v[1],v[4]]
==>[v[4],v[6]]

I am attaching the follow-up part for reference.

(
    g.V().hasLabel("person").
    order().by("age")
    .as("x")
    .local(
        union(
            select("x"),
            select("x")
        ).fold()
    ).sideEffect(
        project("first", "second")
            .by(unfold().limit(1))
            .by(unfold().skip(1))
        .coalesce(
            select("first").out("age_lt").unfold(),
            choose(
                math("second - first").by("age").is(lt(5)),
                addE("age_lt").from(select("first")).to(select("second"))
            )
        )
    ).none()
)

Solution

  • You could do this with using a partitioning pattern that has this form (where "2" is your partition size):

    g.V().fold().
      emit().
      until(__.not(__.unfold())).
      repeat(__.skip(local, 2)).
      filter(__.unfold()).
      limit(local, 2)
    

    but rather than skipping "2" inside the repeat() you just skip "1" since you only want to advance the traversers ahead by "1", thus:

    gremlin> g.V().hasLabel("person").
    ......1>   order().by("age").fold().
    ......2>   emit().
    ......3>   until(__.not(__.unfold())).
    ......4>   repeat(__.skip(local,1)).
    ......5>   filter(__.unfold()).
    ......6>   limit(local,2)
    ==>[v[2],v[1]]
    ==>[v[1],v[4]]
    ==>[v[4],v[6]]
    ==>[v[6]]
    

    Then, just get rid of any trailing unpaired items:

    gremlin> g.V().hasLabel("person").
    ......1>   order().by("age").fold().
    ......2>   emit().
    ......3>   until(__.not(__.unfold())).
    ......4>   repeat(__.skip(local,1)).
    ......5>   filter(__.unfold()).
    ......6>   limit(local,2).
    ......7>   filter(count(local).is(2))
    ==>[v[2],v[1]]
    ==>[v[1],v[4]]
    ==>[v[4],v[6]]