The use of an index for injection was just for purpose of demonstrating
things quickly. You could maybe use an identity step or something as a
placeholder and then inject/replace on that step instance.  It's not
perfect - just thinking out loud. There is a ticket out there to make
TraversalStrategy writing "better". Ultimately, anything we do in that
regard would probably help this problem.

On Thu, Apr 21, 2016 at 10:32 AM, Dylan Millikin <dylan.milli...@gmail.com>
wrote:

> Ohh, I wasn't aware of that. It looks like TraversalHelper has a bunch of
> really useful stuff for these scenarios.
> You are indeed grasping the problem.
> Looking at the signatures there are still grey areas and things that aren't
> really usable (like having to know the index of the injection point) and
> I'm not really sure how this translates to sub traversals like:
>
> g.V().hasLabel("project").union(out('dev')/** inject here **/,
> out('company'))
> yet still work with:
> g.V().hasLabel("person")/** inject here **/.out('friend').out('company');
>
> Is there perhaps a way of including a flag somewhere and have that server
> as the index id ?
>
> Anyways this is definitely what I'm talking about. I'm guessing that there
> may be some conflicts from the fact that method signatures aren't
> necessarily kept in gremlin language variants. Mostly around changing
> existing steps, but if there's a way to get this to work in broader use
> cases it would definitely fit the bill.
>
> Cheers for that. I'll definitely dig a bit deeper around this.
>
> On Thu, Apr 21, 2016 at 10:18 AM, Stephen Mallette <spmalle...@gmail.com>
> wrote:
>
> > I'm not sure what you mean by:
> >
> > > Why is this not an option: It boils down to the fact that you still
> > can't modify
> > a traversal "after the fact".
> >
> > You can modify the Traversal up to the point where you iterate it and
> > TraversalStrategy are applied.
> >
> > gremlin> base = g.V().hasLabel('person').out();[]
> > gremlin> filter = __.has('age',29)
> > gremlin> TraversalHelper.insertTraversal(1,filter,base);[]
> > gremlin> base.toString()
> > ==>[GraphStep(vertex,[]), HasStep([~label.eq(person)]),
> > HasStep([age.eq(29)]), VertexStep(OUT,vertex)]
> > gremlin> base
> > ==>v[3]
> > ==>v[2]
> > ==>v[4]
> >
> > Note how I injected an anonymous Traversal (i.e. the "filter") into the
> > middle of a "base" Traversal. This is a little known function that is
> > probably familiar to TraversalStrategy developers only, but it exists. I
> > suppose more advanced forms of Gremlin Language Variants should/could
> have
> > this kind of capability - I guess the point is that it's possible and
> > arguably better than string manipulation. You might not agree, but am I
> at
> > least grasping the problem you're trying to express?
> >
> >
> > On Thu, Apr 21, 2016 at 9:49 AM, Dylan Millikin <
> dylan.milli...@gmail.com>
> > wrote:
> >
> > > Essentially what is required is to be able to "build" traversals with a
> > > complete disregard for the order of the steps you're adding. Think of
> it
> > as
> > > adding entries to a match(). It doesn't matter what order you add those
> > > entries in.
> > > This is something that is very "declarative" in nature but is a
> > requirement
> > > when developing complex applications that need modularity. You also
> need
> > > this in an imperative setting as you may want control on how the data
> is
> > > fetched.
> > >
> > > On Thu, Apr 21, 2016 at 9:39 AM, Dylan Millikin <
> > dylan.milli...@gmail.com>
> > > wrote:
> > >
> > > > Yeah there are some more complex situations. You actually left out
> the
> > > > final out() in your example. For instance just keeping things simple,
> > > > your base query could be required to be reused in many places. So the
> > > > following is not an option:
> > > >
> > > > base = g.V().hasLabel('person');[]
> > > > /** apply some filters like you did **/
> > > > base.out('company')
> > > >
> > > > Why is this not an option: It boils down to the fact that you still
> > can't
> > > > modify a traversal "after the fact".
> > > > Your reusable base is not complete without the out() step. Therefore,
> > > > using this model you can't store the base query and test it
> separately.
> > > You
> > > > also have to append the out step everywhere you use this base, which
> in
> > > > addition to creating a lot of duplicate code can also not be an
> option
> > > when
> > > > queries are generated automatically. Sometimes you don't even really
> > know
> > > > what the base query is, you just know that it contains certain
> > "injection
> > > > points".
> > > > To give you a few examples, these following base queries all have the
> > > same
> > > > injection point that allows them to be edited with the same filters:
> > > >
> > > > g.V().hasLabel("person")/** inject here **/.out('company');
> > > > g.V().hasLabel("person")/** inject here
> > **/.out('friend').out('company');
> > > > g.V().has("person", "name", "marko").out('friend')/** inject here
> > > > **/.out('company');
> > > >
> > > > These are all valid. My filters apply to "people" but the traversals
> > > > leading to and from these people can be anything. And
> programmatically
> > I
> > > > have no way of knowing what the traversal is. This gets increasingly
> > > > complexe with injection points in sub-traversals, or when injecting
> > full
> > > > traversals with their own injection points, and so on.
> > > >
> > > > Also your example doesn't cover changing existing steps.
> > > >
> > > > I don't know if that sheds anymore light.
> > > >
> > > > On Thu, Apr 21, 2016 at 9:14 AM, Stephen Mallette <
> > spmalle...@gmail.com>
> > > > wrote:
> > > >
> > > >> So "query building" is where you hold string representations of
> steps
> > or
> > > >> groups of steps and then have some logic that concatenates them
> > > together.
> > > >> I
> > > >> guess my question is why are "strings" a requirement for that? It
> > seems
> > > >> like you could do the same query builder stuff with an actual
> > Traversal
> > > >> object in whatever Gremlin Language Variant you were working with.
> How
> > > is
> > > >> string concatenation different than this:
> > > >>
> > > >> gremlin> graph = TinkerFactory.createModern()
> > > >> ==>tinkergraph[vertices:6 edges:6]
> > > >> gremlin> g = graph.traversal()
> > > >> ==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
> > > >> gremlin> base = g.V().hasLabel('person');[]
> > > >> gremlin> addFilters = { age, name, t ->
> > > >> gremlin>   t = age > 0 ? t.has('age',age) : t
> > > >> gremlin>   !name.isEmpty() ? t.has('name',name) : t
> > > >> gremlin> }
> > > >> ==>groovysh_evaluate$_run_closure1@503d56b5
> > > >> gremlin> traversal = addFilters(29,'',base);[]
> > > >> gremlin> traversal.toString()
> > > >> ==>[GraphStep(vertex,[]), HasStep([~label.eq(person)]),
> > > >> HasStep([age.eq(29)])]
> > > >> gremlin> traversal
> > > >> ==>v[1]
> > > >>
> > > >> What about DSLs? Maybe filtering logic drops behind a custom step
> > > specific
> > > >> to the domain:
> > > >>
> > > >> g.V().personsWith(29, '')
> > > >>
> > > >> which would basically compile to the same thing as the gremlin
> output
> > > >> above:
> > > >>
> > > >> [GraphStep(vertex,[]), HasStep([~label.eq(person)]),
> > > >> HasStep([age.eq(29)])]
> > > >>
> > > >> Is there some more complex aspect "query building" that can't be
> > handled
> > > >> this way (I know I took a fairly simple example)?
> > > >>
> > > >>
> > > >>
> > > >> On Wed, Apr 20, 2016 at 7:54 PM, Dylan Millikin <
> > > dylan.milli...@gmail.com
> > > >> >
> > > >> wrote:
> > > >>
> > > >> > I've approached this a few times in the past though never really
> in
> > > >> depth.
> > > >> > The idea is that you want separation of logic in your queries,
> > mostly
> > > >> for
> > > >> > maintenance, testing and overall convenience. This takes the form
> of
> > > >> > partial/incomplete traversals that have no start nor end.
> > > >> > One of the simplest applications would be to have a base query and
> > > apply
> > > >> > filters to this query. For example we can imagine a recap page of
> > > >> > everyone's companies:
> > > >> >
> > > >> > base query : g.V().has(label, "person").out('company')
> > > >> >
> > > >> > To this you have a set of filters that are partial traversals and
> > > allow
> > > >> > users to better refine their search:
> > > >> >
> > > >> > older than 30 filter: has("age", gt(30))
> > > >> > male filter: has("gender", "male")
> > > >> >
> > > >> > Now depending on user input you'll want to apply either or both of
> > the
> > > >> > above to "person" in order to obtain something along the lines of:
> > > >> >
> > > >> > g.V().has(label, "person").has("age", gt(30)).has("gender",
> > > >> > "male").out('company')
> > > >> >
> > > >> > Of course there are plenty of ways of doing the above depending on
> > > >> > requirements and complexity. Such as where() or
> > as("a")....select("a")
> > > >> > etc..
> > > >> >
> > > >> > These are simple examples where steps are appended in various
> places
> > > but
> > > >> > you can imagine the same with traversal manipulation such as
> turning
> > > >> > out('company') into out('company', 'organization') where the step
> > gets
> > > >> > altered. This would work the same way if you used
> > > union(out('company'))
> > > >> > instead. You would have to alter the union step like this :
> > > >> > union(out('company'),
> > > >> > out('organization'))
> > > >> >
> > > >> > All of the above are relatively simple but picture having a lot of
> > > very
> > > >> > complex traversal "filters" that sometimes have dependencies on
> > other
> > > >> > filters.
> > > >> > All this is doable but it currently requires looking at the
> gremlin
> > > >> > building process as a query building one rather than native
> support
> > > for
> > > >> the
> > > >> > gremlin language.
> > > >> >
> > > >> > Does that make any sense?
> > > >> >
> > > >> > On Wed, Apr 20, 2016 at 7:15 PM, Stephen Mallette <
> > > spmalle...@gmail.com
> > > >> >
> > > >> > wrote:
> > > >> >
> > > >> > > >  It's imperative that you have the ability to group multiline
> > > >> scripts
> > > >> > > into a single query or the reactivity of your applications will
> > > >> greatly
> > > >> > > suffer.
> > > >> > >
> > > >> > > A fair point and something we might yet address as part of all
> > this
> > > >> > > thinking. RemoteGraph is pretty new and it demonstrated a
> critical
> > > >> aspect
> > > >> > > of communications with Gremlin Server. Now we need to think
> about
> > > how
> > > >> to
> > > >> > > improve upon it.
> > > >> > >
> > > >> > > > Namely having the ability to edit/modify/add steps to an
> already
> > > >> > defined
> > > >> > > traversal.
> > > >> > >
> > > >> > > I don't quite follow that point...could you please elaborate?
> > > >> > >
> > > >> > >
> > > >> > >
> > > >> > >
> > > >> > > On Wed, Apr 20, 2016 at 4:15 PM, Dylan Millikin <
> > > >> > dylan.milli...@gmail.com>
> > > >> > > wrote:
> > > >> > >
> > > >> > > > Nice post,
> > > >> > > >
> > > >> > > > I'm going to jump straight to the end. I think that one of the
> > > >> problems
> > > >> > > of
> > > >> > > > doing an abstraction similar to remoteGraph is that in reality
> > the
> > > >> > > overhead
> > > >> > > > of communicating with the server is too big to make this
> viable.
> > > >> It's
> > > >> > > > imperative that you have the ability to group multiline
> scripts
> > > >> into a
> > > >> > > > single query or the reactivity of your applications will
> greatly
> > > >> > suffer.
> > > >> > > >
> > > >> > > > The Gremlin-java base also has a few limitations that some
> query
> > > >> > builders
> > > >> > > > try to fix (which can only be done if you abandon the idea of
> a
> > > >> natural
> > > >> > > > gremlin language variant in favor of a query builder). Namely
> > > having
> > > >> > the
> > > >> > > > ability to edit/modify/add steps to an already defined
> > traversal.
> > > >> > Though
> > > >> > > in
> > > >> > > > time it might be nice to have these be part of the original
> > > >> > > implementation.
> > > >> > > >
> > > >> > > > I personally love the idea of gremlin language variants. I
> just
> > > >> don't
> > > >> > > think
> > > >> > > > they're production value is any good without some extended
> > > >> > functionality
> > > >> > > > (beyond what gremlin-java currently is).
> > > >> > > >
> > > >> > > > On Wed, Apr 20, 2016 at 3:23 PM, Stephen Mallette <
> > > >> > spmalle...@gmail.com>
> > > >> > > > wrote:
> > > >> > > >
> > > >> > > > > This thread on Gremlin Language Variants has been very
> > > >> interesting:
> > > >> > > > >
> > > >> > > > > https://pony-poc.apache.org/thread.html/Zcazrw7k442xcwc
> > > >> > > > >
> > > >> > > > > I think that this work goes a long way to address two issues
> > > I've
> > > >> > been
> > > >> > > > > concerned about:
> > > >> > > > >
> > > >> > > > > 1. Greater consistency in how different languages do Gremlin
> > > >> > > > > 2. Less fragmentation in terms of libraries and how they
> work
> > so
> > > >> that
> > > >> > > > users
> > > >> > > > > aren't confused with how to get started (though I don't
> think
> > > the
> > > >> > goal
> > > >> > > > here
> > > >> > > > > is to restrict choices or slow down innovation)
> > > >> > > > >
> > > >> > > > > One of the first things we should probably do is start
> > thinking
> > > in
> > > >> > > terms
> > > >> > > > of
> > > >> > > > > the types of libraries that are built on TinkerPop (outside
> of
> > > >> those
> > > >> > > > things
> > > >> > > > > that are Graph Systems) and those are listed here currently:
> > > >> > > > >
> > > >> > > > > http://tinkerpop.apache.org/#graph-libraries
> > > >> > > > >
> > > >> > > > > Marko mentioned to me that he saw the libraries we listed
> here
> > > >> > breaking
> > > >> > > > > into three categories:
> > > >> > > > >
> > > >> > > > > 1. Gremlin Language Variants - which the other thread
> > > demonstrates
> > > >> > > quite
> > > >> > > > > nicely
> > > >> > > > > 2. Gremlin Drivers - the Gremlin Server protocol
> > > implementations -
> > > >> > > those
> > > >> > > > > things that send traversals to Gremlin Server and get back
> > > >> results.
> > > >> > > > > 3. OGM and others - I say "others" because there might be
> > > plugins
> > > >> and
> > > >> > > > other
> > > >> > > > > similar odds and ends
> > > >> > > > >
> > > >> > > > > I like Marko's category system here and I think that having
> > > these
> > > >> > kinds
> > > >> > > > of
> > > >> > > > > categories will help folks organize their libraries to fit
> > into
> > > >> one
> > > >> > of
> > > >> > > > > these spaces and make it easier for users to know what they
> > need
> > > >> to
> > > >> > get
> > > >> > > > in
> > > >> > > > > order to start doing TinkerPop in their language.
> > > >> > > > >
> > > >> > > > > Anyway, the category thing is just setting the stage for
> this
> > > big
> > > >> > > > > bombshell.  I think TinkerPop should consider maintaining
> the
> > > >> Gremlin
> > > >> > > > > Language Variants.
> > > >> > > > >
> > > >> > > > > Heresy! right?
> > > >> > > > >
> > > >> > > > > Well, I think it's the best way to achieve consistency
> across
> > > >> > > languages.
> > > >> > > > > Under this model, TinkerPop provides the base language
> variant
> > > and
> > > >> > > people
> > > >> > > > > can choose to extend upon it, but the base stays tied to our
> > > >> > archetype
> > > >> > > of
> > > >> > > > > Java and we end up with a much more clear story for
> virtually
> > > any
> > > >> > > > > programming language.
> > > >> > > > >
> > > >> > > > > So how do we do this? Slowly and deliberately. We should
> look
> > to
> > > >> only
> > > >> > > > > include language variants where we:
> > > >> > > > >
> > > >> > > > > + have good automation in place (like what Marko did for
> > > Python),
> > > >> > > > > + some competence on the committer list in that language
> > > >> > > > > + a nice testing framework that operates in our standard
> > > >> > build/release
> > > >> > > > > process.
> > > >> > > > >
> > > >> > > > > That's setting a high bar, but if we don't keep it high, I
> > think
> > > >> we
> > > >> > > will
> > > >> > > > be
> > > >> > > > > left unable to properly support and maintain what we hang
> out
> > > >> there.
> > > >> > > > >
> > > >> > > > > I'd also like to express that we should not be looking to
> > > maintain
> > > >> > > > language
> > > >> > > > > drivers. I think that should remain a third-party community
> > > effort
> > > >> > just
> > > >> > > > > like Graph Systems. In other words, we remain a repository
> for
> > > >> > > reference
> > > >> > > > > implementations for everything else. Why? Because, as it
> sits
> > > >> right
> > > >> > > now,
> > > >> > > > > just based on the level of effort for what Marko did with
> > > Python,
> > > >> > > > > maintaining a "base" Gremlin Language Variants shouldn't be
> > > hard.
> > > >> We
> > > >> > > > won't
> > > >> > > > > be building tons of add-on capabilities to the base
> variants -
> > > >> they
> > > >> > > will
> > > >> > > > > pretty much just stay on par with the java archetype.
> Drivers
> > > on
> > > >> the
> > > >> > > > other
> > > >> > > > > hand have lots of implementation details, with many
> different
> > > >> > > > technologies
> > > >> > > > > that could be used, etc.  They have similar complexity to
> > Graph
> > > >> > System
> > > >> > > > > implementations in many ways. I also think that the drivers
> > can
> > > >> > afford
> > > >> > > to
> > > >> > > > > have different APIs and approaches without being detrimental
> > to
> > > >> the
> > > >> > > > > community.
> > > >> > > > >
> > > >> > > > > If gremlin-js-driver wants to do:
> > > >> > > > >
> > > >> > > > > client.submit("g.V()")
> > > >> > > > >
> > > >> > > > > and gremlin-python-driver wants to do:
> > > >> > > > >
> > > >> > > > > client.send("g.V()")
> > > >> > > > >
> > > >> > > > > that's not a big deal.
> > > >> > > > >
> > > >> > > > > The last point that I'll make is that I think Gremlin
> Language
> > > >> > > Variants,
> > > >> > > > > that don't operate on the JVM (e.g. Jython) and use Gremlin
> > > >> Server,
> > > >> > > > should
> > > >> > > > > have some abstraction that is similar to RemoteGraph.
> > > RemoteGraph
> > > >> > > > exposes
> > > >> > > > > a DriverConnection interface that is currently implemented
> by
> > > >> > > > > gremlin-driver.  The DriverConnection is responsible for
> > > sending a
> > > >> > > > > traversal to the server and returning results. It would be
> > nice
> > > if
> > > >> > the
> > > >> > > > > language variants had a similar interface that the various
> > > >> community
> > > >> > > > > drivers could implement. In that way, the user never has to
> do
> > > any
> > > >> > form
> > > >> > > > of:
> > > >> > > > >
> > > >> > > > > client.submit(someGremlinString)
> > > >> > > > >
> > > >> > > > > in any language. We really need to try to make that pattern
> go
> > > >> away
> > > >> > > > across
> > > >> > > > > the TinkerPop community.
> > > >> > > > >
> > > >> > > > > So - that's was a long email. Looking forward to hearing
> some
> > > >> > > discussion
> > > >> > > > on
> > > >> > > > > this.
> > > >> > > > >
> > > >> > > > > Stephen
> > > >> > > > >
> > > >> > > >
> > > >> > >
> > > >> >
> > > >>
> > > >
> > > >
> > >
> >
>

Reply via email to