You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2016/05/05 20:10:57 UTC

[1/2] incubator-tinkerpop git commit: Added recipes framework.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/master d696b38ab -> acd439d15


Added recipes framework.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/b81c82a8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/b81c82a8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/b81c82a8

Branch: refs/heads/master
Commit: b81c82a8de3708d139ce1938df364096b0e07496
Parents: 08d54c6
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue May 3 15:54:51 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue May 3 15:54:51 2016 -0400

----------------------------------------------------------------------
 .../src/recipes/if-then-based-grouping.asciidoc |  70 +++++++++++++
 docs/src/recipes/index.asciidoc                 |  38 +++++++
 docs/src/recipes/shortest-path.asciidoc         |  99 +++++++++++++++++++
 docs/static/images/gremlin-chef.png             | Bin 0 -> 38762 bytes
 docs/static/images/shortest-path.png            | Bin 0 -> 61680 bytes
 pom.xml                                         |  25 +++++
 6 files changed, 232 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/docs/src/recipes/if-then-based-grouping.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/if-then-based-grouping.asciidoc b/docs/src/recipes/if-then-based-grouping.asciidoc
new file mode 100644
index 0000000..fc319b7
--- /dev/null
+++ b/docs/src/recipes/if-then-based-grouping.asciidoc
@@ -0,0 +1,70 @@
+////
+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.
+////
+[[if-then-based-grouping]]
+If-Then Based Grouping
+----------------------
+
+Consider the following traversal over the "modern" toy graph:
+
+[gremlin-groovy,modern]
+----
+g.V().hasLabel('person').groupCount().by('age')
+----
+
+The result is an age distribution that simply shows that every "person" in the graph is of a different age. In some
+cases, this result is exactly what is needed, but sometimes a grouping may need to be transformed to provide a
+different picture of the result. For example, perhaps a grouping on the value "age" would be better represented by
+a domain concept such as "young", "old" and "very old".
+
+[gremlin-groovy,modern]
+----
+g.V().hasLabel("person").groupCount().by(values("age").choose(
+  is(lt(28)),constant("young"),
+  choose(is(lt(30)),
+    constant("old"),
+    constant("very old"))))
+----
+
+Note that the `by` modulator has been altered from simply taking a string key of "age" to take a `Traversal`. That
+inner `Traversal` utilizes `choose` which is like an `if-then-else` clause. The `choose` is nested and would look
+like the following in Java:
+
+[source,java]
+----
+if (age < 28) {
+  return "young";
+} else {
+  if (age < 30) {
+    return "old";
+  } else {
+    return "very old";
+  }
+}
+----
+
+The use of `choose` is a good intutive choice for this `Traversal` as it is a natural mapping to `if-then-else`, but
+there is another option to consider with `coalesce`:
+
+[gremlin-groovy,modern]
+----
+g.V().hasLabel("person").groupCount().by(values("age").coalesce(
+  is(lt(28)).constant("young"),
+  is(lt(30)).constant("old"),
+             constant("very old")))
+----
+
+The answer is the same, but this traversal removes the nested `choose`, which makes it easier to read.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/docs/src/recipes/index.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/index.asciidoc b/docs/src/recipes/index.asciidoc
new file mode 100644
index 0000000..3ff99d1
--- /dev/null
+++ b/docs/src/recipes/index.asciidoc
@@ -0,0 +1,38 @@
+////
+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.
+////
+image::apache-tinkerpop-logo.png[width=500,link="http://tinkerpop.apache.org"]
+
+*x.y.z*
+
+:toc-position: left
+
+Recipes
+=======
+
+image:gremlin-chef.png[width=120,float=left] All programming languages tend to have
+link:https://en.wikipedia.org/wiki/Software_design_pattern[patterns of usage] for commonly occurring problems. Gremlin
+is not different in that respect. There are many commonly occurring traversal themes that have general applicability
+to any graph. Gremlin Recipes present these common traversal patterns and methods of usage that will
+provide some basic building blocks for virtually any graph in any domain.
+
+Recipes assume general familiarity with Gremlin and the TinkerPop stack. Be sure to have read the
+link:http://tinkerpop.apache.org/docs/x.y.z/tutorials/getting-started[Getting Started] tutorial and the
+link:http://tinkerpop.apache.org/docs/x.y.z/tutorials/the-gremlin-console/[The Gremlin Console] tutorial.
+
+include::shortest-path.asciidoc[]
+
+include::if-then-based-grouping.asciidoc[]

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/docs/src/recipes/shortest-path.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/shortest-path.asciidoc b/docs/src/recipes/shortest-path.asciidoc
new file mode 100644
index 0000000..161646a
--- /dev/null
+++ b/docs/src/recipes/shortest-path.asciidoc
@@ -0,0 +1,99 @@
+////
+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.
+////
+[[shortest-path]]
+Shortest Path
+-------------
+
+image:shortest-path.png[width=300]
+
+When working with a graph, it is often necessary to identify the
+link:https://en.wikipedia.org/wiki/Shortest_path_problem[shortest path] between two identified vertices. The following
+is a simple example that identifies the shortest path between vertex "1" and vertex "5" while traversing over out edges:
+
+[gremlin-groovy]
+----
+graph = TinkerGraph.open()
+v1 = graph.addVertex(T.id, 1)
+v2 = graph.addVertex(T.id, 2)
+v3 = graph.addVertex(T.id, 3)
+v4 = graph.addVertex(T.id, 4)
+v5 = graph.addVertex(T.id, 5)
+v1.addEdge("knows", v2)
+v2.addEdge("knows", v4)
+v4.addEdge("knows", v5)
+v2.addEdge("knows", v3)
+v3.addEdge("knows", v4)
+g = graph.traversal()
+g.V(1).repeat(out().simplePath()).until(hasId(5)).path().limit(1)     <1>
+g.V(1).repeat(out().simplePath()).until(hasId(5)).path().count(local) <2>
+g.V(1).repeat(out().simplePath()).until(hasId(5)).path().group().by(count(local)).next()  <3>
+----
+
+<1> The traversal starts at vertex with the identifier of "1" and repeatedly traverses on out edges "until" it finds a
+vertex with an identifier of "5". The inclusion of `simplePath` within the `repeat` is present to filter out repeated
+paths. The traversal terminates with `limit` in this case as the first path returned will be the shortest one. Of
+course, it is possible for there to be more than one path in the graph of the same length (i.e. two or more paths of
+length three), but this example is not considering that.
+<2> It might be interesting to know the path lengths for all paths between vertex "1" and "5".
+<3> Alternatively, one might wish to do a path length distribution over all the paths.
+
+The previous example defines the length of the path by the number of vertices in the path, but the "path" might also
+be measured by data within the graph itself. The following example use the same graph structure as the previous example,
+but includes a "weight" on the edges, that will be used to help determine the "cost" of a particular path:
+
+[gremlin-groovy]
+----
+graph = TinkerGraph.open()
+v1 = graph.addVertex(T.id, 1)
+v2 = graph.addVertex(T.id, 2)
+v3 = graph.addVertex(T.id, 3)
+v4 = graph.addVertex(T.id, 4)
+v5 = graph.addVertex(T.id, 5)
+v1.addEdge("knows", v2, "weight", 1.25)
+v2.addEdge("knows", v4, "weight", 1.5)
+v4.addEdge("knows", v5, "weight", 0.25)
+v2.addEdge("knows", v3, "weight", 0.25)
+v3.addEdge("knows", v4, "weight", 0.25)
+g = graph.traversal()
+g.V(1).repeat(out().simplePath()).until(hasId(5)).path().group().by(count(local)).next()  <1>
+g.V(1).repeat(outE().inV().simplePath()).until(hasId(5)).                                 <2>
+  path().by(coalesce(values('weight'), constant(0.0))).map(unfold().sum())
+g.V(1).repeat(outE().inV().simplePath()).until(hasId(5)).
+  path().by(constant(0.0)).by('weight').map(unfold().sum())                               <3>
+g.V(1).repeat(outE().inV().simplePath()).until(hasId(5)).                                 <4>
+  path().as('p').
+  map(unfold().coalesce(values('weight'),constant(0.0)).sum()).as('cost').
+  select('cost','p')
+----
+
+<1> Note that the shortest path as determined by the structure of the graph is the same.
+<2> Calculate the "cost" of the path as determined by the weight on the edges. As the "weight" data is on the edges
+between the vertices, it is necessary to change the contents of the `repeat` step to use `outE().inV()` so that the
+edge is included in the path. The path is then post-processed with a `by` modulator that extracts the "weight" value.
+The traversal uses `coalesce` as there is a mixture of vertices and edges in the path and the traversal is only
+interested in edge elements that can return a "weight" property. The final part of the traversal executes a map
+function over each path, unfolding it and summing the weights.
+<3> The same traversal as the one above it, but avoids the use of `coalesce` with the use of two `by` modulators. The
+`by` modulator is applied in a round-robin fashion, so the first `by` will always apply to a vertex (as it is the first
+item in every path) and the second `by` will always apply to an edge (as it always follows the vertex in the path).
+<4> The output of the previous examples of the "cost" wasn't terribly useful as it didn't include which path had the
+calculated cost. With some slight modifications given the use of `select` it becomes possible to include the path in
+the output. Note that the path with the lowest "cost" actually has a longer path length as determined by the graph
+structure.
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/docs/static/images/gremlin-chef.png
----------------------------------------------------------------------
diff --git a/docs/static/images/gremlin-chef.png b/docs/static/images/gremlin-chef.png
new file mode 100644
index 0000000..f728a56
Binary files /dev/null and b/docs/static/images/gremlin-chef.png differ

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/docs/static/images/shortest-path.png
----------------------------------------------------------------------
diff --git a/docs/static/images/shortest-path.png b/docs/static/images/shortest-path.png
new file mode 100644
index 0000000..52f1d47
Binary files /dev/null and b/docs/static/images/shortest-path.png differ

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b81c82a8/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 28e932c..bba5e3b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -782,6 +782,31 @@ limitations under the License.
                                 </configuration>
                             </execution>
                             <execution>
+                                <id>recipe-book</id>
+                                <phase>generate-resources</phase>
+                                <goals>
+                                    <goal>process-asciidoc</goal>
+                                </goals>
+                                <configuration>
+                                    <sourceDirectory>${asciidoc.input.dir}/recipes</sourceDirectory>
+                                    <sourceDocumentName>index.asciidoc</sourceDocumentName>
+                                    <outputDirectory>${htmlsingle.output.dir}/recipes</outputDirectory>
+                                    <backend>html5</backend>
+                                    <doctype>book</doctype>
+                                    <attributes>
+                                        <imagesdir>../images</imagesdir>
+                                        <encoding>UTF-8</encoding>
+                                        <toc>true</toc>
+                                        <toclevels>2</toclevels>
+                                        <toc-position>left</toc-position>
+                                        <stylesdir>${asciidoctor.style.dir}</stylesdir>
+                                        <stylesheet>tinkerpop.css</stylesheet>
+                                        <source-highlighter>coderay</source-highlighter>
+                                        <basedir>${project.basedir}</basedir>
+                                    </attributes>
+                                </configuration>
+                            </execution>
+                            <execution>
                                 <id>tutorial-getting-started</id>
                                 <phase>generate-resources</phase>
                                 <goals>


[2/2] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/TINKERPOP-1286'

Posted by sp...@apache.org.
Merge remote-tracking branch 'origin/TINKERPOP-1286'


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/acd439d1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/acd439d1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/acd439d1

Branch: refs/heads/master
Commit: acd439d15127467779ea54a834759ee9c163df2e
Parents: d696b38 b81c82a
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu May 5 16:10:44 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu May 5 16:10:44 2016 -0400

----------------------------------------------------------------------
 .../src/recipes/if-then-based-grouping.asciidoc |  70 +++++++++++++
 docs/src/recipes/index.asciidoc                 |  38 +++++++
 docs/src/recipes/shortest-path.asciidoc         |  99 +++++++++++++++++++
 docs/static/images/gremlin-chef.png             | Bin 0 -> 38762 bytes
 docs/static/images/shortest-path.png            | Bin 0 -> 61680 bytes
 pom.xml                                         |  25 +++++
 6 files changed, 232 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/acd439d1/pom.xml
----------------------------------------------------------------------