You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tinkerpop.apache.org by Marko Rodriguez <ok...@gmail.com> on 2015/08/25 17:44:18 UTC

[Proposal] Everything is a traversal.

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


Re: [Proposal] Everything is a traversal.

Posted by Matt Frantz <ma...@gmail.com>.
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 <ok...@gmail.com>
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 <ma...@gmail.com>
> 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 <ok...@gmail.com>
> > 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 <ma...@gmail.com>
> >> 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 <okrammarko@gmail.com
> >
> >>> 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 <ok...@gmail.com>
> >> 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
> >>>>>
> >>>>
> >>>>
> >>
> >>
>
>

Re: [Proposal] Everything is a traversal.

Posted by Marko Rodriguez <ok...@gmail.com>.
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 <ma...@gmail.com> 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 <ok...@gmail.com>
> 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 <ma...@gmail.com>
>> 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 <ok...@gmail.com>
>>> 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 <ok...@gmail.com>
>> 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
>>>>> 
>>>> 
>>>> 
>> 
>> 


Re: [Proposal] Everything is a traversal.

Posted by Matt Frantz <ma...@gmail.com>.
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 <ok...@gmail.com>
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 <ma...@gmail.com>
> 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 <ok...@gmail.com>
> > 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 <ok...@gmail.com>
> 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
> >>>
> >>
> >>
>
>

Re: [Proposal] Everything is a traversal.

Posted by Marko Rodriguez <ok...@gmail.com>.
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 <ma...@gmail.com> 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 <ok...@gmail.com>
> 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 <ok...@gmail.com> 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
>>> 
>> 
>> 


Re: [Proposal] Everything is a traversal.

Posted by Matt Frantz <ma...@gmail.com>.
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 <ok...@gmail.com>
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 <ok...@gmail.com> 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
> >
>
>

Re: [Proposal] Everything is a traversal.

Posted by Marko Rodriguez <ok...@gmail.com>.
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 <ok...@gmail.com> 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
>