What would be the interpretation if multiple arguments to mutator steps are iterators? Without guaranteed order, the "zip" interpretation is meaningless. A cross-product interpretation would be robust, but not necessarily useful unless coupled with `where` (like a relational join).
On Wed, Aug 26, 2015 at 8:15 AM, Marko Rodriguez <[email protected]> wrote: > Hey, > > Here is the final question I have. If the "x" is an iterable, should we > iterate it or does "x" have to reference a vertex. For instance. > > > g.V.aggregate('x').as('a').select('x').unfold().addE("knows").to('a') > > OR > > g.V.aggregate('x').as('a').addE("knows").to('x') > > While the latter looks enticing, I don't know if its a good thing. Trying > to think through the ramifications… However, a better example of why > iterable/iterator support would be smart: > > g.V.as > ('a').out('knows').as('b').addE('friendsParent').from('a').to(select('b').out('parent')) > > Given that the to() is a traversal, it is an iterator/iterable. > > Any thoughts on the matter beyond just "that would be nice" based on how > this plays within the larger scope of the language itself. For instance, no > step-modulators support traversal beyond .next(). E.g. > > g.V.groupCount().by(out('knows').values('name')) > > Will just group by the first person they knows name. Not all names. To do > all names, its: > > g.V.groupCount().by(out('knows').values('name').fold()) > > If to() and from() supported iterable/iterator, these would differ from > the rest of the language. You may so, "thats fine." Well, then what about > properties, shouldn't they then support iterable/iterator unfolding as you > may have a "zip"-style. > > g.V.as > ('a').out('knows').as('b').addE('friendsParent').from('a').to(select('b').out('parent')).property('weight',select('a').out('knows').values('weight')) > > …….but now we are just getting crazy and complex. I would prefer to NOT > support to()/from() being "iterable/iterator" compliant, but it sure is > damn convenient………. > > Thoughts?, > Marko. > > http://markorodriguez.com > > On Aug 26, 2015, at 8:06 AM, Matt Frantz <[email protected]> > wrote: > > > Now all we need is the mid-traversal V/E: > > https://issues.apache.org/jira/browse/TINKERPOP3-762 > > > > Then, the reasoning API will be fully operational. > > > > On Tue, Aug 25, 2015 at 6:58 PM, Marko Rodriguez <[email protected]> > > wrote: > > > >> Hi, > >> > >> In theory, yes. The problem is that we don't have a g.inject() off > >> GraphTraversalSource. If you use an anonymous traversal, there is no > graph > >> and thus, AddXXXStep doesn't know the graph to add things too. Thus, we > >> need something like: > >> > >> g.inject('alice', 'bob', 'charlie').as('name'). > >> addV('person').property('name', select('name')) > >> > >> NOTE: In your emails and in your JIRA tickets you tend to word wrap on > the > >> "." and thus, you can't copy/paste your examples into the console. For > >> instance: > >> > >> BAD: > >> > >> __('alice', 'bob', 'charlie').as('name') > >> .addV('person').property('name', select('name')) > >> > >> GOOD: > >> > >> __('alice', 'bob', 'charlie').as('name'). > >> addV('person').property('name', select('name')) > >> > >> Easy to add… In fact, probably will just add that now. If people have a > >> better idea than g.inject(…), please advise. > >> > >> <coding….> > >> > >> Okay. Added to mutating_traverser/ branch (will push once integration > >> tests complete). Here is your example: > >> > >> gremlin> g.inject('alice', 'bob', > >> 'charlie').as('a').addV('person').property('name', select('a')) > >> ==>v[0] > >> ==>v[2] > >> ==>v[4] > >> gremlin> g.V().valueMap() > >> ==>{name=[alice]} > >> ==>{name=[bob]} > >> ==>{name=[charlie]} > >> > >> Pretty freakin' sweet. > >> > >> Thanks, > >> Marko. > >> > >> http://markorodriguez.com > >> > >> On Aug 25, 2015, at 5:36 PM, Matt Frantz <[email protected]> > >> wrote: > >> > >>> If you're starting from scratch (empty graph), would you use an > anonymous > >>> traversal to add elements? > >>> > >>> __('alice', 'bob', 'charlie').as('name') > >>> .addV('person').property('name', select('name')) > >>> > >>> > >>> On Tue, Aug 25, 2015 at 3:31 PM, Marko Rodriguez <[email protected] > > > >>> wrote: > >>> > >>>> Hello, > >>>> > >>>> The mutating_traverser/ branch has the implementation of the proposal > >>>> discussed in the previous email. > >>>> > >>>> https://github.com/apache/incubator-tinkerpop/tree/mutating_traverser > >>>> Here is the key change to the GraphTraversal DSL: > >>>> > >>>> > >> > https://github.com/apache/incubator-tinkerpop/blob/mutating_traverser/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java#L640-L726 > >>>> > >>>> Here is a Gremlin Console session so people can see how nice the new > >> model > >>>> is: > >>>> > >>>> gremlin> g = TinkerFactory.createModern().traversal() > >>>> ==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard] > >>>> gremlin> g.V().as('a').out('created').addE('createdBy').to('a') > >>>> ==>e[12][3-createdBy->1] > >>>> ==>e[13][5-createdBy->4] > >>>> ==>e[14][3-createdBy->4] > >>>> ==>e[15][3-createdBy->6] > >>>> gremlin> g.V().as('a').outE('created').as('b').inV(). > >>>> > >>>> > >> > addE('createdBy').to('a').property('weight',select('b').values('weight')). > >>>> valueMap() > >>>> ==>[weight:0.4] > >>>> ==>[weight:1.0] > >>>> ==>[weight:0.4] > >>>> ==>[weight:0.2] > >>>> gremlin> g.V().as('a').addE('pet').to(addV('animal').property('name', > >>>> select('a').by('name').map{it.get() + "'s pet"})) > >>>> ==>e[26][1-pet->24] > >>>> ==>e[29][2-pet->27] > >>>> ==>e[32][3-pet->30] > >>>> ==>e[35][4-pet->33] > >>>> ==>e[38][5-pet->36] > >>>> ==>e[41][6-pet->39] > >>>> gremlin> g.V().hasLabel('animal').valueMap() > >>>> ==>[name:[josh's pet]] > >>>> ==>[name:[ripple's pet]] > >>>> ==>[name:[peter's pet]] > >>>> ==>[name:[marko's pet]] > >>>> ==>[name:[vadas's pet]] > >>>> ==>[name:[lop's pet]] > >>>> > >>>> Pretty wicked, eh? > >>>> > >>>> Note that that the old Mutation methods still exist (though they are > >>>> @Deprecated) and they simply call those new AddXXXStep steps > >> accordingly. > >>>> The only thing left to do is update the documentation. > >>>> > >>>> Please review the work and if you are happy, I can merge master/ and > >> then > >>>> update the docs. > >>>> > >>>> Thanks, > >>>> Marko. > >>>> > >>>> http://markorodriguez.com > >>>> > >>>> On Aug 25, 2015, at 9:44 AM, Marko Rodriguez <[email protected]> > >> wrote: > >>>> > >>>>> Hello, > >>>>> > >>>>> TinkerPop3 made a stance against TinkerPop2 and said: "there are no > >> such > >>>> thing as lambdas --- lambdas are traversals!" > >>>>> > >>>>> Next --- the mutation steps in TinkerPop3 are sorta clunky and ugly. > >>>> Moreover, people want mid-traversal parameterization. That is, > something > >>>> like: > >>>>> > >>>>> addV(T.label, select("a").label()) > >>>>> > >>>>> This got us to thinking. EVERYTHING IS A TRAVERSAL. There are no such > >>>> things a primitives. Gremlin works with only one type of object -- > >>>> Traversal. While this sounds crazy, its actual realization into > >> TinkerPop > >>>> 3.1.0 would be simple. However, our mutation steps as we have them > now, > >>>> would be @Deprecated. :( Everything else would stay the same. :) > >> Ignoring > >>>> the general theory of "EVERYTHING IS A TRAVERSAL," lets look at a > >> practical > >>>> day one ramification. > >>>>> > >>>>> Here is the thread of thought: > >>>>> https://issues.apache.org/jira/browse/TINKERPOP3-799 > >>>>> > >>>>> Here is a break down of what of what we propose for TinkerPop 3.1.0. > >>>>> > >>>>> addV("person").property("name","marko") > >>>>> addV("person").property("name",select("a").by("name")) > >>>>> addE("likes").from("a").to("b") > >>>>> > >>>> > >> > addE("knows").from(select("a").in("likes")).to(select("b").in("employees")) > >>>>> addE("likes").from(select("a").in("likes")).to("a") > >>>>> > >>>> > >> > addE("likes").from("a").to("b").property(select("a").by("key"),select("a").by("value")) > >>>>> out(select("a").label()) > >>>>> > >>>>> In short, every step's parameters can be traversals which are > evaluated > >>>> at runtime. Thus, the query is parameterized by the traverser. > >> Psychedelic. > >>>>> > >>>>> For now, I'm not so interested in out(select("a").label()) as much as > >> in > >>>> cleaning up the mutation steps (property(), addV(), addE()) as this is > >>>> where people seem to want this type of runtime parameterization and > >> where > >>>> our current GraphTraversal API is weak. > >>>>> > >>>>> If anyone has any thoughts on the matter, please espouse them. > >>>>> > >>>>> *** Note for vendors. I know Titan, so I will show how this is crazy > >> for > >>>> Titan and hopefully other vendors see the complexity. When a user does > >>>> out(select("a").label()), then Titan's vertex-centric index step will > >> NOT > >>>> have the edge label at compile-time, but will have to compute for each > >> and > >>>> every traverser. I have already created a very nice object called > >>>> "Parameters" which makes this easy, but still…….. This is also why I > >> just > >>>> want to focus on the mutation steps for now as those are not vendor > >>>> optimized (as far as I know) and it provides us the most bang for our > >> buck. > >>>>> > >>>>> Thanks, > >>>>> Marko. > >>>>> > >>>>> http://markorodriguez.com > >>>>> > >>>> > >>>> > >> > >> > >
