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 > >> > > > > > >> > > > > >> > > > >> > > >> > > > > >