Search code examples
javacyphertinkerpoptinkerpop3

Match NOT in Tinkerpop traversal


I'd like to match all b1, where no node b2 exists as depicted below. enter image description here This is some kind of a 2-hop asymmetry. Note that the non-existent b2 must link to the same c:C as b1, so other (a2) --> (b3) --> (a1) can be ignored as long as b3 has no edge to c:C.

I tried the following...

graph.traversal().V()
    .match(
        as("c").hasLabel("C"),

        as("a").hasLabel("A")
        .out().hasLabel("B").as("b1")
        .where(out().as("c"))
        .out().hasLabel("A").as("a2"),

        not(
        as("a2")
        .out().hasLabel("B").as("b2")
        .where(out().as("c")
        .out().as("a1")
    )
)

...but second MATCH step throws an exception:

java.lang.IllegalStateException: The provided match pattern is unsolvable: [[MatchStartStep(a1), HasStep([~label.eq(A)]), VertexStep(OUT,vertex), HasStep([~label.eq(B)]), WhereTraversalStep([WhereStartStep, VertexStep(OUT,vertex), WhereEndStep(c)])@[b1], VertexStep(OUT,vertex), HasStep([~label.eq(A)]), MatchEndStep(a2)], [MatchStartStep(a2), HasStep([~label.eq(B)]), WhereTraversalStep([NotStep([WhereStartStep, VertexStep(OUT,edge)])]), WhereTraversalStep([WhereStartStep, VertexStep(OUT,vertex)@[c], VertexStep(OUT,vertex), WhereEndStep(a1)])@[b2], MatchEndStep, MatchEndStep]]

I can't even match this is Cypher, unfortunately.


Solution

  • Suddenly, I found a solution which avoids scope problems:

    graph.traversal().V()
        as("a").hasLabel("A")
        .out().hasLabel("B").as("b1")
        .where(out().hasLabel("C"))
        .out().hasLabel("A").as("a2")
        .where(
            not(
                out().hasLabel("B")
                    .where(out().hasLabel("C"))
                    .out().as("a")
            )
        )