Repository: tinkerpop Updated Branches: refs/heads/TINKERPOP-1396 8a59e4825 -> ee50a6faf (forced update)
Added new recipe for Traversal Induced Values. Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ee50a6fa Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ee50a6fa Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ee50a6fa Branch: refs/heads/TINKERPOP-1396 Commit: ee50a6fafabeef14b99dee308e71d9cc98619977 Parents: 8f7218d Author: Stephen Mallette <[email protected]> Authored: Wed Aug 3 18:54:28 2016 -0400 Committer: Stephen Mallette <[email protected]> Committed: Thu Aug 4 06:10:40 2016 -0400 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + docs/src/recipes/index.asciidoc | 2 + .../recipes/traversal-induced-values.asciidoc | 83 ++++++++++++++++++++ 3 files changed, 86 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ee50a6fa/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 22d2b32..43f5cc4 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima TinkerPop 3.2.2 (NOT OFFICIALLY RELEASED YET) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Added new recipe for "Traversal Induced Values". * Fixed a potential leak of a `ReferenceCounted` resource in Gremlin Server. * Added class registrations for `Map.Entry` implementations to `GryoMapper`. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ee50a6fa/docs/src/recipes/index.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/recipes/index.asciidoc b/docs/src/recipes/index.asciidoc index 18b5c9e..67a7932 100644 --- a/docs/src/recipes/index.asciidoc +++ b/docs/src/recipes/index.asciidoc @@ -46,6 +46,8 @@ include::cycle-detection.asciidoc[] include::centrality.asciidoc[] +include::traversal-induced-values.asciidoc[] + Implementation Recipes ====================== http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ee50a6fa/docs/src/recipes/traversal-induced-values.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/recipes/traversal-induced-values.asciidoc b/docs/src/recipes/traversal-induced-values.asciidoc new file mode 100644 index 0000000..6adefc7 --- /dev/null +++ b/docs/src/recipes/traversal-induced-values.asciidoc @@ -0,0 +1,83 @@ +//// +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +//// +[[traversal-induced-values]] +Traversal Induced Values +------------------------ + +The parameters of a `Traversal` can be known ahead of time as constants or might otherwise be passed in as dynamic +arguments. + +[gremlin-groovy,modern] +---- +g.V().has('name','marko').out('knows').has('age', gt(29)).values('name') +---- + +In plain language, the above Gremlin asks, "What are the names of the people who Marko knows who are over the age of +29?". In this case, "29" is known as a constant to the traversal. Of course, if the question is changed slightly to +instead ask, "What are the names of the people who Marko knows who are older than he is?", the hardcoding of "29" will +no longer suffice. There are multiple ways Gremlin would allow this second question to be answered. The first is +obvious to any programmer - use a variable: + +[gremlin-groovy,modern] +---- +marko = g.V().has('name','marko').next() +g.V(marko).out('knows').has('age', gt(marko.value('age'))).values('name') +---- + +The downside to this approach is that it takes two separate traversals to answer the question. Ideally, there should +be a single traversal, that can query "marko" once, determine his `age` and then use that for the value supplied to +filter the people he knows. In this way the _value_ for the `age` filter is _induced_ from the `Traversal` itself. + +[gremlin-groovy,modern] +---- +g.V().has('name','marko').as('marko'). <1> + out('knows').as('friend'). <2> + filter(select('marko','friend').by('age'). <3> + where('friend', gt('marko'))). <4> + values('name') +---- + +<1> Find the "marko" `Vertex` and label it as "marko". +<2> Traverse out on the "knows" edges to the adjacent `Vertex` and label it as "person". +<3> Filter the incoming "person" vertices. It is within this filter, that the traversal induced values are utilized. +The inner `select` grabs the "marko" vertex and the current "friend". The `by` modulator extracts the "age" from both +of those vertices which yields a `Map` with two keys, "marko" and "friend", where the value of each is the "age". +<4> The `Map` produced in the previous step can then be filtered with `where` to only return a result if the "friend" +age is greater than the "marko" age. If this is successful, then the `filter` step from the previous line will succeed +and allow the "friend" vertex to pass through. + +This traversal could also be written declaratively with `match` step as follows: + +[gremlin-groovy,modern] +---- +g.V().has('name','marko').match( + __.as('marko').values('age').as('a'), + __.as('marko').out('knows').as('friend'), + __.as('friend').values('age').as('b') + ).where('b', gt('a')).select('friend'). + values('name') +---- + +Traversal induced values are not just for filtering. They can also be used when writing the values of the properties +of one `Vertex` to another: + +[gremlin-groovy,modern] +---- +g.V().has('name', 'marko').as('marko'). + out('created').property('creator', select('marko').by('name')) +g.V().has('name', 'marko').out('created').valueMap() +---- \ No newline at end of file
