[
https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17267638#comment-17267638
]
Christopher Smith edited comment on TINKERPOP-2502 at 1/19/21, 4:11 AM:
------------------------------------------------------------------------
I'm writing what's essentially a mini-OGM for Groovy, to be eventually
implemented as a set of compile-time AST transformations to generate the
repetitive part of mapping traversals. This is an extension method (in Java)
that allows writing {{gts.addV(newPerson, PERSON_WRITER)}} (the logic might
look familiar):
{code:java}
@SuppressWarnings("unchecked") // both traversal paths end in a Vertex
public static <V extends HasLabelAndId> GraphTraversal<Vertex, Vertex>
addV(GraphTraversalSource self, V entity, VertexWriter<V> writer) {
// https://stackoverflow.com/a/46053115/1189885
return self
.V(entity.getLabelAndId().getId()).fold()
.coalesce(
whenExists(true, unfold()),
whenExists(false, writer.createVertex(start(), entity))
)
.filter(select("existed").is(false))
.select("element");
}
private static <A> GraphTraversal<A, Map<String, Object>> whenExists(boolean
exists, GraphTraversal<A, ?> gt) {
return gt.project("element", "existed").by(identity()).by(constant(exists));
}
{code}
However, this method can _only_ be called as {{gts.addV}}; it _cannot_ be
called as {{__.addV}}, because there is no common supertype. Furthermore, while
in the anonymous case (say, creating multiple vertices with edges between them)
I could call {{__.start()}} to get a traversal to feed to the pipeline above,
as I do to pass to {{createVertex}}, if I already have a
{{GraphTraversalSource}} there's no way to turn it into a {{GraphTraversal}}
except through {{V}}, {{E}}, {{addV}}, {{addE}}, or {{inject}} (potentially
problematic with some implementations).
Instead, if I had a method such as {{GraphTraversalSource#start()}} with the
obvious semantics, I could modify the above method to accept a
{{GraphTraversal}}, consume it for both anonymous and regular traversals, and
provide sugar to adapt those cases onto it. If I understand the semantics
correctly, it would be as simple as cloning the other entry-point methods and
dropping the {{addStep}} call.
was (Author: chrylis):
I'm writing what's essentially a mini-OGM for Groovy, to be eventually
implemented as a set of compile-time AST transformations to generate the
repetitive part of mapping traversals. This is an extension method (in Java)
that allows writing {{gts.addV(newPerson, PERSON_WRITER)}} (the logic might
look familiar):
{code:java}
@SuppressWarnings("unchecked") // both traversal paths end in a Vertex
public static <V extends HasLabelAndId> GraphTraversal<Vertex, Vertex>
addV(GraphTraversalSource self, V entity, VertexWriter<V> writer) {
// https://stackoverflow.com/a/46053115/1189885
return self
.V(entity.getLabelAndId().getId()).fold()
.coalesce(
whenExists(true, unfold()),
whenExists(false, writer.createVertex(start(), entity))
)
.filter(select("existed").is(false))
.select("element");
}
private static <A> GraphTraversal<A, Map<String, Object>> whenExists(boolean
exists, GraphTraversal<A, ?> gt) {
return gt.project("element", "existed").by(identity()).by(constant(exists));
}
{code}
However, this method can _only_ be called as {{gts.addV}}; it _cannot_ be
called as {{__.addV}}, because there is no common supertype. Furthermore, while
in the anonymous case (say, creating multiple vertices with edges between them)
I could call {{__.start()}} to get a traversal to feed to the pipeline above,
as I do to pass to {{createVertex}}, if I already have a
{{GraphTraversalSource}} there's no way to turn it into a {{GraphTraversal}}
except through {{V}}, {{E}}, {{addV}}, {{addE}}, or {{inject}} (potentially
problematic with some implementations).
Instead, if I had a method such as {{GraphTraversalSource#start()}} with the
obvious semantics, I could modify the above method to accept a
{{GraphTraversal}}, consume it for both anonymous and regular traversals, and
provide sugar to adapt those cases onto it.
> Consistent start API for anonymous and regular traversals
> ---------------------------------------------------------
>
> Key: TINKERPOP-2502
> URL: https://issues.apache.org/jira/browse/TINKERPOP-2502
> Project: TinkerPop
> Issue Type: Improvement
> Components: process
> Affects Versions: 3.4.9
> Reporter: Christopher Smith
> Priority: Minor
>
> I am writing a graph-based application and am taking advantage of the
> method-based nature of Gremlin to librarify some of my common usage patterns.
> However, I'm encountering a frustrating problem where I frequently need to be
> able to attach the same traversal steps to either a real
> {{GraphTraversalSource}} or an anonymous traversal (usually for some nested
> reason like a coalesced conditional insert).
> The methods on {{__}} are mostly static, but I can call {{__.start()}} to
> obtain a live {{GraphTraversal}} object and then proceed from there (invoking
> {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however,
> requires me to invoke the method {{GraphTraversalSource#addV}} to get
> started, and there's no common base type. I think I could theoretically use
> something like {{inject()}}, but that seems particularly odd.
> It would be helpful to either have both {{GraphTraversal}} and
> {{GraphTraversalSource}} implement a common interface holding the "start
> opcodes" or to have a {{GraphTraversalSource#start()}} method that could be
> used to obtain a "blank" traversal.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)