Search code examples
gremlintinkerpopamazon-neptunetinkerpop3

Is there a nicer way to force a Gremlin query to fail when it discovers an invalid state?


It would be nice if there was a way to have a Gremlin query terminate with some kind of error message if, as part of the query, it is determined that there is no point proceeding further. One not very nice way of doing this is to trigger an exception. For example something like this:

gremlin> g.inject(1).math('_/0')
Division by zero!  

Is there a better way to trigger a more meaningful exception when a query determines that there is no need continuing?


Solution

  • Starting with the Apache TinkerPop 3.6.0 release (April 2022) a new fail step is now part of the Gremlin language. So for the simple case in the question, you can do something like this:

    g.inject(1).fail('The query encountered an issue')
    

    which when run yields a much nicer exception that an application can catch. When run using the Gremlin console, here is the output from the fail step.

    >gremlin g.inject(1).fail('The query encountered an issue') 
    
    fail() Step Triggered
    =================================================================
    Message  > The query encountered an issue
    Traverser> 1
      Bulk   > 1
    Traversal> inject((int) 1).fail("The query encountered an issue")
    Metadata > {}
    =================================================================   
    

    Building on this, a slightly more real world example might be where we expect a node to exist and if we discover it does not, we want to fail immediately.

    gremlin> g.addV('Dog').property('name','Toby')
    ==>v[9]
    
    gremlin> g.V().has('name','Toby').fold().coalesce(unfold().constant('I found Toby'),fail('I did not find Toby'))
    ==>I found Toby
    
    gremlin> g.V().drop()
    
    gremlin> g.V().has('name','Toby').fold().coalesce(unfold().constant('I found Toby'),fail('I did not find Toby'))
    
    fail() Step Triggered
    ==================================================================================================================================
    ===
    Message  > I did not find Toby
    Traverser> []
      Bulk   > 1
    Traversal> fail("I did not find Toby")
    Parent   > CoalesceStep [V().has("name","Toby").fold().coalesce(__.unfold().constant("I found Toby"),__.fail("I did not find Toby"
    ))]
    Metadata > {}
    ==================================================================================================================================
    ===