gremlin.net: how can I connect an anonymous traveral to a regular traversal in gremlin.net?


shapeshifter <shapesh...@...>
 

Sorry if something like this has been answered elsewhere (hard to know what to search on).

I have a pretty simple traversal (albeit with a slightly messy projection step) that looks something like this:

g.V(root).out().order().by(id).range(1000,2000).project("v","e").....)  // project step omitted for brevity

As you can see, it uses range for returning paged results. However, on the first results page only, I need to return the total vertex count of the graph too. I've got this working using something like:

g.V(root).out().union(identity().count(), identity().order().by(id).range(0,1000).project("v","e").......)

This works fine for my needs. I've been able to translate this to c#/gremlin.net and successfully run and parsed the results.

The problem is there a chunk of duplicated code in doing so, namely the order and projection step that I need on both versions of the query but in different places.

Given that I have the 'core' part of the traversal, effectively:
coreT = g.V(root).out()

I only know how to implement it somelthing like:
if (page == 1)
coreT
.Union<object>(__.Identity().Count(), __.Identity()                        
.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
.Project<object>("projectedV", "projectedE")
// etc.
else
coreT.
.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
.Project<object>("projectedV", "projectedE")
// etc.

I know I can create the .Order()....Project()... part as an anonymous traversal:
var suffix = 
                      __.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
                      .Project<object>("projectedV", "projectedE")
// etc.

Question is, can I append this to the existing 'core' traversal as if I had added it using fluent syntax? I want to be able able to reduce my code to something (VERY ROUGHLY!) like:
if (page==1)
vertexTraversal.Union<object>(__.Identity().Count(), __.Identity() + suffix)
else
vertexTraversal .= suffix

Is this even possible?

I appreciate that some people will try to suggest an alternative solution to my paging solution, and while help is always appreciated, I would like to improve my understanding of gremlin.net by finding out if appending/merginf traversals is possible.


Florian Hockmann <f...@...>
 

I would probably implement this as a Domain Specific Language (DSL) which is described in the TinkerPop docs for Gremlin.Net. Your combination of Order().By(), Range(), and Project() could then be a custom step of your DSL:

public static class CustomTraversalExtensions
{
   
public static GraphTraversal<Vertex, IDictionary<string, object>> OrderByWithProject(this GraphTraversal<Vertex, Vertex> t, long low, long high)
   
{
       
return t.Order().By(__.Id())
           
.Range<Vertex>(Scope.Global, low, high)
           
.Project<object>("projectedV", "projectedE");
   
}
}

Since you also want to be able to use this as an anonymous traversal as an argument to the Union() step, you also need an anonymous version of this step (e.g., one that starts a traversal instead of being applied to an existing one):

public static class __Custom
{
   
public static GraphTraversal<object, IDictionary<string, object>> OrderByWithProject(long low, long high)
   
{
       
return __.Order().By(__.Id())
           
.Range<Vertex>(Scope.Global, low, high)
           
.Project<object>("projectedV", "projectedE");
   
}
}

Now you can use these two steps like this:

var t = Traversal().V();

    var page = 1;

    if (page == 1)
        t.Union<Vertex>(__.Count(), OrderByWithProject(1, 1000));
    else
        t.OrderByWithProject(1, 1000);

Note that you need a static using of your __Custom class (or write it as __Custom.OrderByWithProject(1, 1000)).

Am Freitag, 5. Juni 2020 18:34:01 UTC+2 schrieb shapeshifter:

Sorry if something like this has been answered elsewhere (hard to know what to search on).

I have a pretty simple traversal (albeit with a slightly messy projection step) that looks something like this:

g.V(root).out().order().by(id).range(1000,2000).project("v","e").....)  // project step omitted for brevity

As you can see, it uses range for returning paged results. However, on the first results page only, I need to return the total vertex count of the graph too. I've got this working using something like:

g.V(root).out().union(identity().count(), identity().order().by(id).range(0,1000).project("v","e").......)

This works fine for my needs. I've been able to translate this to c#/gremlin.net and successfully run and parsed the results.

The problem is there a chunk of duplicated code in doing so, namely the order and projection step that I need on both versions of the query but in different places.

Given that I have the 'core' part of the traversal, effectively:
coreT = g.V(root).out()

I only know how to implement it somelthing like:
if (page == 1)
coreT
.Union<object>(__.Identity().Count(), __.Identity()                        
.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
.Project<object>("projectedV", "projectedE")
// etc.
else
coreT.
.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
.Project<object>("projectedV", "projectedE")
// etc.

I know I can create the .Order()....Project()... part as an anonymous traversal:
var suffix = 
                      __.Order().By(__.Id()).Range<GVertex>(Scope.Global, low, high)
                      .Project<object>("projectedV", "projectedE")
// etc.

Question is, can I append this to the existing 'core' traversal as if I had added it using fluent syntax? I want to be able able to reduce my code to something (VERY ROUGHLY!) like:
if (page==1)
vertexTraversal.Union<object>(__.Identity().Count(), __.Identity() + suffix)
else
vertexTraversal .= suffix

Is this even possible?

I appreciate that some people will try to suggest an alternative solution to my paging solution, and while help is always appreciated, I would like to improve my understanding of gremlin.net by finding out if appending/merginf traversals is possible.


shapeshifter <shapesh...@...>
 

Thank you very much, Florian, this was pretty much what I needed.