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 2015/11/20 12:55:27 UTC

[03/15] incubator-tinkerpop git commit: Made subdirectories for various "books" in the docs.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc46d649/docs/src/tutorials-getting-started.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/tutorials-getting-started.asciidoc b/docs/src/tutorials-getting-started.asciidoc
deleted file mode 100644
index 8787e57..0000000
--- a/docs/src/tutorials-getting-started.asciidoc
+++ /dev/null
@@ -1,571 +0,0 @@
-////
-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]
-
-Getting Started
-===============
-
-link:http://tinkerpop.com[Apache TinkerPop] is an open source Graph Computing Framework. Within itself, TinkerPop
-represents a large collection of capabilities and technologies and, in its wider ecosystem, an additionally extended
-world of link:http://tinkerpop.incubator.apache.org/#graph-systems[third-party contributed] graph libraries and
-systems. TinkerPop's ecosystem can appear complex to newcomers of all experience, especially when glancing at the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/index.html[reference documentation] for the first time.
-
-So, where do you get started with TinkerPop? How do you dive in quickly and get productive? Well - Gremlin, the
-most recognizable citizen of The TinkerPop, is here to help with this thirty minute tutorial. That's right - in just
-thirty short minutes, you too can be fit to start building graph applications with TinkerPop. Welcome to _The
-TinkerPop Workout - by Gremlin_!
-
-image::gremlin-gym.png[width=1024]
-
-The First Five Minutes
-----------------------
-
-It is quite possible to learn a lot in just five minutes with TinkerPop, but before doing so, a proper introduction of
-your trainer is in order. Meet Gremlin!
-
-image:gremlin-standing.png[width=125]
-
-Gremlin helps you navigate the vertices and edges of a graph. He is essentially your query language to graph
-databases, as link:http://sql2gremlin.com/[SQL] is the query language to relational databases. To tell Gremlin how
-he should "traverse" the graph (i.e. what you want your query to do) you need a way to provide him commands in the
-language he understands - and, of course, that language is called "Gremlin". For this task, you need one of
-TinkerPop's most important tools: link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#gremlin-console[The Gremlin Console].
-
-Download the console, unpackage it and start it:
-
-[source,text]
-----
-$ curl -L -O https://www.apache.org/dist/incubator/tinkerpop/x.y.z/apache-gremlin-console-x.y.z-bin.zip
-$ unzip apache-gremlin-console-x.y.z-bin.zip
-$ cd apache-gremlin-console-x.y.z-bin.zip
-$ bin/gremlin.sh
-
-         \,,,/
-         (o o)
------oOOo-(3)-oOOo-----
-plugin activated: tinkerpop.server
-plugin activated: tinkerpop.utilities
-plugin activated: tinkerpop.tinkergraph
-gremlin>
-----
-
-TIP: Windows users may use the included `bin/gremlin.bat` file to start the Gremlin Console.
-
-The Gremlin Console is a link:http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop[REPL environment],
-which provides a nice way to learn Gremlin as you get immediate feedback for the code that you enter. This eliminates
-the more complex need to "create a project" to try things out. The console is not just for "getting started" however.
-You will find yourself using it for a variety of TinkerPop-related activities, such as loading data, administering
-graphs, working out complex traversals, etc.
-
-To get Gremlin to traverse a graph, you need a `Graph` instance, which holds the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_the_graph_structure[structure] and data of the
-graph. TinkerPop is a graph abstraction layer over different graph databases and different graph processors, so there
-are many `Graph` instances you can choose from to instantiate in the console. The best `Graph` instance to start with
-however is link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#tinkergraph-gremlin[TinkerGraph]. TinkerGraph
-is a fast, in-memory graph database with a small handful of configuration options, making it a good choice for beginners.
-
-TIP: TinkerGraph is not just a toy for beginners. It is useful in analyzing subgraphs taken from a large graph,
-working with a small static graph that doesn't change much, writing unit tests and other use cases where the graph
-can fit in memory.
-
-TIP: Resist the temptation to "get started" with more complex databases like link:http://thinkaurelius.github.io/titan/[Titan]
-or to delve into how to get link:http://tinkerpop.incubator.apache.org/docs/x.y.zg/#gremlin-server[Gremlin Server]
-working properly. Focusing on the basics, presented in this guide, builds a good foundation for all the other things
-TinkerPop offers.
-
-To make your process even easier, start with one of TinkerPop's "toy" graphs. These are "small" graphs designed to
-provide a quick start into querying. It is good to get familiar with them, as almost all TinkerPop documentation is based
-on them and when you need help and have to come to the link:http://groups.google.com/group/gremlin-users[mailing list],
-a failing example put in the context of the toy graphs can usually get you a fast answer to your problem.
-
-For your first graph, use the "Modern" graph which looks like this:
-
-image:tinkerpop-modern.png[width=500]
-
-It can be instantiated in the console this way:
-
-[gremlin-groovy]
-----
-graph = TinkerFactory.createModern()
-g = graph.traversal()
-----
-
-The first command creates a `Graph` instance named `graph`, which thus provides a reference to the data you want
-Gremlin to traverse. Unfortunately, just having `graph` doesn't provide Gremlin enough context to do his job. You
-also need something called a `TraversalSource`, which is generated by the second command. The `TraversalSource`
-provides additional information to Gremlin (such as the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#traversalstrategy[traversal strategies]
-to apply and the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#graphcomputer[traversal engine] to use) which
-provides him guidance on how to execute his trip around the `Graph`.
-
-With your `TraversalSource` `g` available it is now possible to ask Gremlin to traverse the `Graph`:
-
-[gremlin-groovy,modern]
-----
-g.V()    <1>
-g.V(1)    <2>
-g.V(1).values('name')    <3>
-g.V(1).outE('knows')    <4>
-g.V(1).outE('knows').inV().values('name')    <5>
-g.V(1).out('knows').values('name')    <6>
-g.V(1).out('knows').has('age', gt(30)).values('name')    <7>
-----
-
-<1> Get all the vertices in the `Graph`.
-<2> Get a vertex with the unique identifier of "1".
-<3> Get the value of the `name` property on vertex with the unique identifier of "1".
-<4> Get the edges with the label "knows" for the vertex with the unique identifier of "1".
-<5> Get the names of the people that the vertex with the unique identifier of "1" "knows".
-<6> Note that when one uses `outE().inV()` as shown in the previous command, this can be shortened to just `out()`
-(similar to `inE().inV()` and `in` for incoming edges).
-<7> Get the names of the people vertex "1" knows who are over the age of 30.
-
-IMPORTANT: A `Traversal` is essentially an `Iterator` so if you have code like `x = g.V()`, the `x` does not contain
-the results of the `g.V()` query.  Rather, that statement assigns an `Iterator` value to `x`. To get your results,
-you would then need to iterate through `x`. This understanding is *important* because in the context of the console
-typing `g.V()` instantly returns a value. The console does some magic for you by noticing that `g.V()` returns
-an `Iterator` and then automatically iterates the results. In short, when writing Gremlin outside of the console
-always remember that you must iterate your `Traversal` manually in some way for it to do anything.
-
-In this first five minutes with Gremlin, you've gotten the Gremlin Console installed, instantiated a `Graph` and
-`TraversalSource`, wrote some traversals and hopefully learned something about TinkerPop in general. You've only
-scratched the surface of what there is to know, but those accomplishments will help enable your understanding of the
-detailed sections to come.
-
-The Next Fifteen Minutes
-------------------------
-
-In the first five minutes of _The TinkerPop Workout - by Gremlin_, you learned some basics for traversing graphs. Of
-course, there wasn't much discussion about what a graph is. A graph is a collection of vertices (i.e. nodes, dots)
-and edges (i.e. relationships, lines), where a vertex is an entity which represents some domain object (e.g. a person,
-a place, etc.) and an edge represents the relationship between two vertices.
-
-image:modern-edge-1-to-3-1.png[width=300]
-
-The diagram above shows a graph with two vertices, one with a unique identifier of "1" and another with a unique
-identifier of "3". There is a edge connecting the two with a unique identifier of "9". It is important to consider
-that the edge has a direction which goes _out_ from vertex "1" and _in_ to vertex "3'.
-
-IMPORTANT: Most TinkerPop implementations do not allow for identifier assignment. They will rather assign
-their own identifiers and ignore assigned identifiers that you attempt to assign to them.
-
-A graph with elements that just have identifiers does not make for much of a database. To give some meaning to
-this basic structure, vertices and edges can each be given labels to categorize them.
-
-image:modern-edge-1-to-3-2.png[width=300]
-
-You can now see that a vertex "1" is a "person" and vertex "3" is a "software" vertex. They are joined by a "created"
-edge which allows you to see that a "person created software". The "label" and the "id" are reserved attributes of
-vertices and edges, but you can add your own arbitrary properties as well:
-
-image:modern-edge-1-to-3-3.png[width=325]
-
-This model is referred to as a _property graph_ and it provides a flexible and intuitive way in which to model your
-data.
-
-Creating a Graph
-^^^^^^^^^^^^^^^^
-
-As intuitive as it is to you, it is perhaps more intuitive to Gremlin himself, as vertices, edges and properties make
-up the very elements of his existence. It is indeed helpful to think of our friend, Gremlin, moving about a graph when
-developing traversals, as picturing his position as the link:http://tinkerpop.incubator.apache.org/docs/3.0.2-incubating/#_the_traverser[traverser]
-helps orient where you need him to go next. Let's use the two vertex, one edge graph we've been discussing above
-as an example. First, you need to create this graph:
-
-[gremlin-groovy]
-----
-graph = TinkerGraph.open()
-v1 = graph.addVertex(id, 1, label, "person", "name", "marko", "age", 29)
-v2 = graph.addVertex(id, 3, label, "software", "name", "lop", "lang", "java")
-v1.addEdge("created", v2, id, 9, "weight", 0.4)
-----
-
-There are a number of important things to consider in the above code. First, recall that `id` and `label` are
-"reserved" for special usage in TinkerPop. Those "keys" supplied to the creation method are statically imported to
-the console. You would normally refer to them as `T.id` and `T.label`.
-
-NOTE: The fully qualified name for `T` is `org.apache.tinkerpop.gremlin.structure.T`.
-
-Second, don't forget that you are working with TinkerGraph which allows for identifier assignment. That is _not_ the
-case with most graph databases.
-
-Finally, the label for an `Edge` is required and is thus part of the method signature of `addEdge()`. It is the first
-parameter supplied, followed by the `Vertex` to which `v1` should be connected. Therefore, this usage of `addEdge` is
-creating an edge that goes _out_ of `v1` and into `v2` with a label of "created".
-
-Graph Traversal - Staying Simple
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Now that Gremlin knows where the graph data is, you can ask him to get you some data from it by doing a traversal,
-which you can think of as executing some link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_the_graph_process[process]
-over the structure of the graph. We can form our question in English and then translate it to Gremlin. For this
-initial example, let's ask Gremlin: "What software has Marko created?"
-
-To answer this question, we would want Gremlin to:
-
-. Find "marko" in the graph
-. Walk along the "created" edges to "software" vertices
-. Select the "name" property of the "software" vertices
-
-The English-based steps above largely translate to Gremlin's position in the graph and to the steps we need to take
-to ask him to answer our question. By stringing these steps together, we form a `Traversal` or the sequence of programmatic
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#graph-traversal-steps[steps] Gremlin needs to perform
-in order to get you an answer.
-
-Let's start with finding "marko". This operation is a filtering step as it searches the full set of vertices to match
-those that have the "name" property value of "marko". This can be done with the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#has-step[has()] step as follows:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko')
-----
-
-NOTE: The variable `g` is the `TraversalSource`, which was introduced in the "The First Five Minutes". The
-`TraversalSource` is created with `graph.traversal()` and is the object used to spawn new traversals.
-
-We can picture this traversal in our little graph with Gremlin sitting on vertex "1".
-
-image:modern-edge-1-to-3-1-gremlin.png[width=325]
-
-When Gremlin is on a vertex or an edge, he has access to all the properties that are available to that element.
-
-IMPORTANT: The above query iterates all the vertices in the graph to get its answer. That's fine for our little example,
-but for multi-million or billion edge graphs that is a big problem. To solve this problem, you should look to use
-indices. TinkerPop does not provide an abstraction for index management. You should consult the documentation of the
-graph you have chosen and utilize its native API to create indices which will then speed up these types of lookups. Your
-traversals will remain unchanged however, as the indices will be used transparently at execution time.
-
-Now that Gremlin has found "marko", he can now consider the next step in the traversal where we ask him to "walk"
-along "created" edges to "software" vertices. As described earlier, edges have direction, so we have to tell Gremlin
-what direction to follow. In this case, we want him to traverse on outgoing edges from the "marko" vertex. For this,
-we use the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#vertex-steps[outE] step.
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').outE('created')
-----
-
-At this point, you can picture Gremlin moving from the "marko" vertex to the "created" edge.
-
-image:modern-edge-1-to-3-2-gremlin.png[width=325]
-
-To get to the vertex on the other end of the edge, you need to tell Gremlin to move from the edge to the incoming
-vertex with `inV()`.
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').outE('created').inV()
-----
-
-You can now picture Gremlin on the "software" vertex as follows:
-
-image:modern-edge-1-to-3-3-gremlin.png[width=325]
-
-As you are not asking Gremlin to do anything with the properties of the "created" edge, you can simplify the
-statement above with:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').out('created')
-----
-
-Finally, now that Gremlin has reached the "software that Marko created", he has access to the properties of the
-"software" vertex and you can therefore ask Gremlin to extract the value of the "name" property as follows:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').out('created').values('name')
-----
-
-You should now be able to see the connection Gremlin has to the structure of the graph and how Gremlin maneuvers from
-vertices to edges and so on. Your ability to string together steps to ask Gremlin to do more complex things, depends
-on your understanding of these basic concepts.
-
-Graph Traversal - Increasing Complexity
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Armed with the knowledge from the previous section, let's ask Gremlin to perform some more difficult traversal tasks.
-There's not much more that can be done with the "baby" graph we had, so let's return to the "modern" toy graph from
-the "five minutes section". Recall that you can create this `Graph` and establish a `TraversalSource` with:
-
-[gremlin-groovy]
-----
-graph = TinkerFactory.createModern()
-g = graph.traversal()
-----
-
-Earlier we'd used the `has()` step to tell Gremlin how to find the "marko" vertex. Let's look at some other ways to
-use `has()`. What if we wanted Gremlin to find the "age" values of both "vadas" and "marko"? In this case we could
-use the `within` comparator with `has()` as follows:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name',within('vadas','marko')).values('age')
-----
-
-It is worth noting that `within` is statically imported from `P` to the Gremlin Console (much like `T` is, as described
-earlier).
-
-NOTE: The fully qualified name for `P` is `org.apache.tinkerpop.gremlin.process.traversal.P`.
-
-If we wanted to ask Gremlin the average age of "vadas" and "marko" we could use the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#mean-step[mean()] step as follows:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name',within('vadas','marko')).values('age').mean()
-----
-
-Another method of filtering is seen in the use of the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#where-step[where]
-step. We know how to find the "software" that "marko" created:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').out('created')
-----
-
-image:gremlin-on-software-vertex.png[width=350,float=right] Let's extend on that query to try to learn who "marko"
-collaborates with when it comes to the software he created. In other words, let's try to answer the question of: "Who
-are the people that marko develops software with?" To do that, we should first picture Gremlin where we left him in
-the previous query.  He was standing on the "software" vertex. To find out who "created" that "software", we need to
-have Gremlin traverse back _in_ along the "created" edges to find the "person" vertices tied to it.
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').out('created').in('created').values('name')
-----
-
-So that's nice, we can see that "peter", "josh" and "marko" are both responsible for creating "lop". Of course, we already
-know about the involvement of "marko" and it seems strange to say that "marko" collaborates with himself, so excluding
-"marko" from the results seems logical. The following traversal handles that exclusion:
-
-[gremlin-groovy,modern]
-----
-g.V().has('name','marko').as('exclude').out('created').in('created').where(neq('exclude')).values('name')
-----
-
-We made two additions to the traversal to make it exclude "marko" from the results. First, we added the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#as-step[as()] step. The `as()` step is not really a "step",
-but a "step modulator" - something that adds features to a step or the traversal. Here, the `as('exclude')` labels
-the `has()` step with the name "exclude" and all values that pass through that step are held in that label for later
-use. In this case, the "marko" vertex is the only vertex to pass through that point, so it is held in "exclude".
-
-The other addition that was made was the `where()` step which is a filter step like `has()`. The `where()` is
-positioned after the `in()` step that has "person" vertices, which means that the `where()` filter is occurring
-on the list of "marko" collaborators. The `where()` specifies that the "person" vertices passing through it should
-not equal (i.e. `neq()`) the contents of the "exclude" label. As it just contains the "marko" vertex, the `where()`
-filters out the "marko" that we get when we traverse back _in_ on the "created" edges.
-
-You will find many uses of `as()`. Here it is in combination with link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#select-step[select]:
-
-[gremlin-groovy,modern]
-----
-g.V().as('a').out().as('b').out().as('c').select('a','b','c')
-----
-
-In the above example, we tell Gremlin to iterate through all vertices and traverse _out_ twice from each. Gremlin
-will label each vertex in that path with "a", "b" and "c", respectively. We can then use `select` to extract the
-contents of that label.
-
-Another common but important step is the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#group-step[group()]
-step and its related step modulator called link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#by-step[by()]. If
-we wanted to ask Gremlin to group all the vertices in the graph by their vertex label we could do:
-
-[gremlin-groovy,modern]
-----
-g.V().group().by(label)
-----
-
-The use of `by()` here provides the mechanism by which to do the grouping. In this case, we've asked Gremlin to
-use the `label` (which, again, is an automatic static import from `T` in the console). We can't really tell much
-about our distribution though because we just have vertex unique identifiers as output. To make that nicer we
-could ask Gremlin to get us the value of the "name" property from those vertices, by supplying another `by()`
-modulator to `group()` to transform the values.
-
-[gremlin-groovy,modern]
-----
-g.V().group().by(label).by('name')
-----
-
-In this section, you have learned a bit more about what property graphs are and how Gremlin interacts with them.
-You also learned how to envision Gremlin moving about a graph and how to use some of the more complex, but commonly
-utilized traversal steps. You are now ready to think about TinkerPop in terms of its wider applicability to
-graph computing.
-
-The Final Ten Minutes
----------------------
-
-In these final ten minutes of _The TinkerPop Workout - by Gremlin_ we'll look at TinkerPop from a higher level and
-introduce different features of the stack in order to orient you with what it offers. In this way, you can
-identify areas of interest and dig into the details from there.
-
-Why TinkerPop?
-^^^^^^^^^^^^^^
-
-image:provider-integration.png[float=right,width=350] The goal of TinkerPop, as a Graph Computing Framework, is to make it
-easy for developers to create graph applications by providing APIs and tools that simplify their endeavors. One of
-the fundamental aspects to what TinkerPop offers in this area lies in the fact that TinkerPop is an abstraction layer
-over different graph databases and different graph processors. As an abstraction layer, TinkerPop provides a way to
-avoid vendor lock-in to a specific database or processor. This capability provides immense value to developers who
-are thus afforded options in their architecture and development because:
-
-* They can try different implementations using the same code to decide which is best for their environment.
-* They can grow into a particular implementation if they so desire - start with a graph that is designed to scale
-within a single machine and then later switch to a graph that is designed to scale horizontally.
-* They can feel more confident in graph technology choices, as advances in the state of different provider
-implementations are behind TinkerPop APIs, which open the possibility to switch providers with limited impact.
-
-TinkerPop has always had the vision of being an abstraction over different graph databases. That much
-is not new and dates back to TinkerPop 1.x. It is in TinkerPop 3.x however that we see the introduction of the notion
-that TinkerPop is also an abstraction over different graph processors like link:http://spark.apache.org[Spark] and
-link:http://giraph.apache.org/[Giraph]. The scope of this tutorial does not permit it to delve into
-"graph processors", but the short story is that the same Gremlin statement we wrote in the examples above can be
-executed to run in distributed fashion over Spark or Hadoop. The changes required to the code to do this are not
-in the traversal itself, but in the definition of the `TraversalSource`. You can again see why we encourage, graph
-operations to be executed through that class as opposed to just using `Graph`. You can read more about these
-features in this section on link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#hadoop-gremlin[hadoop-gremlin].
-
-TIP: To maintain an abstraction over `Graph` creation use `GraphFactory.open()` to construct new instances. See
-the documentation for individual `Graph` implementations to learn about the configuration options to provide.
-
-Loading Data
-^^^^^^^^^^^^
-
-image:gremlin-to-the-7.png[width=100,float=left] There are many strategies for getting data into your graph. As you are just
-getting started, let's look the more simple methods aimed at "smaller" graphs. A "small" graph, in this context, is
-one that has less than ten million edges. The most direct way to load this data is to write a Groovy script that can
-be executed in the Gremlin Console, a tool that you should be well familiar with at this point. For our example, let's
-use the link:http://snap.stanford.edu/data/wiki-Vote.html[Wikipedia Vote Network] data set which contains 7,115
-vertices and 103,689 edges.
-
-[source,text]
-----
-$ curl -L -O http://snap.stanford.edu/data/wiki-Vote.txt.gz
-$ gunzip wiki-Vote.txt.gz
-----
-
-The data is contained in a tab-delimited structure where vertices are Wikipedia users and edges from one user to
-another implies a "vote" relationship. Here is the script to parse the file and generate the `Graph` instance using
-TinkerGraph:
-
-[source,groovy]
-----
-graph = TinkerGraph.open()
-graph.createIndex('userId', Vertex.class) <1>
-
-g = graph.traversal()
-
-getOrCreate = { id ->
-  g.V().has('userId', id).tryNext().orElseGet{ g.addV('userId', id).next() }
-}
-
-new File('wiki-Vote.txt').eachLine {
-  if (!it.startsWith("#")){
-    (fromVertex, toVertex) = it.split('\t').collect(getOrCreate) <2>
-    fromVertex.addEdge('votesFor', toVertex)
-  }
-}
-----
-
-<1> To ensure fast lookups of vertices, we need an index. The `createIndex()` method is a method native to
-TinkerGraph. Please consult your graph databases documentation for their index creation approaches.
-<2> We are iterating each line of the `wiki-Vote.txt` file and this line splits the line on the delimiter, then
-uses some neat Groovy syntax to apply the `getOrCreate()` function to each of the two `userId` fields encountered in
-the line and stores those vertices in the `fromVertex` and `toVertex` variables respectively.
-
-NOTE: While this is a tab-delimited structure, this same pattern can be applied
-to any data source you require and Groovy tends to have nice libraries that can help making working with data
-link:http://thinkaurelius.com/2013/02/04/polyglot-persistence-and-query-with-gremlin/[quite enjoyable].
-
-WARNING: Take care if using a `Graph` implementation that supports
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#transactions[transactions]. As TinkerGraph does not, there is
-no need to `commit()`.  If your `Graph` does support transactions, intermediate commits during load will need to be
-applied.
-
-To load larger data sets you should read about the
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#bulkloadervertexprogram[BulkLoaderVertexProgram] (BLVP), which
-provides a generalized method for loading graphs of virtually any size.
-
-Gremlin Server
-^^^^^^^^^^^^^^
-
-image:gremlin-server-protocol.png[width=325,float=right] link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#gremlin-server[Gremlin Server]
-provides a way to remotely execute Gremlin scripts against one or more `Graph` instances hosted within it. It does
-this by exposing different endpoints, such as link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_rest[REST]
-and link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_java[websockets], which allow a request
-containing a Gremlin script to be processed with results returned.
-
-[source,text]
-----
-$ curl -L -O https://www.apache.org/dist/incubator/tinkerpop/x.y.z/apache-gremlin-server-x.y.z-bin.zip
-$ unzip apache-gremlin-server-x.y.z-bin.zip
-$ cd apache-gremlin-server-x.y.z-bin.zip
-$ bin/gremlin-server.sh conf/gremlin-server-modern.yaml
-[INFO] GremlinServer -
-         \,,,/
-         (o o)
------oOOo-(3)-oOOo-----
-
-[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-rest-modern.yaml
-...
-[INFO] GremlinServer$1 - Channel started at port 8182.
-----
-
-[source,text]
-$ curl -X POST -d "{\"gremlin\":\"g.V(x).out().values('name')\", \"language\":\"gremlin-groovy\", \"bindings\":{\"x\":1}}" "http://localhost:8182"
-
-[source,json]
-----
-{
-    "requestId": "abe3be05-1e86-481a-85e0-c59ad8a37c6b",
-    "status": {
-        "message": "",
-        "code": 200,
-        "attributes": {}
-    },
-    "result": {
-        "data": [
-            "lop",
-            "vadas",
-            "josh"
-        ],
-        "meta": {}
-    }
-}
-----
-
-IMPORTANT: Take careful note of the use of "bindings" in the arguments on the request. These are variables that are
-applied to the script on execution and is essentially a way to parameterize your scripts. This "parameterization" is
-critical to link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_best_practices[performance].  Whenever
-possible, parameterize your queries.
-
-As mentioned earlier, Gremlin Server can also be configured with a websockets endpoint. This endpoint has an
-embedded link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_developing_a_driver[subprotocol] that allow a
-compliant driver to communicate with it.  TinkerPop supplies a
-link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_java[reference driver] written in Java, but
-there are drivers developed by third-parties for other link:http://tinkerpop.incubator.apache.org/#graph-libraries[languages]
-such as Python, Javascript, etc. Gremlin Server therefore represents the method by which non-JVM languages can
-interact with TinkerPop.
-
-Conclusion
-^^^^^^^^^^
-
-...and that is the end of _The TinkerPop Workout - by Gremlin_. You are hopefully feeling more confident in your
-TinkerPop skills and have a good overview of what the stack has to offer, as well as some entry points to further
-research within the reference documentation. Welcome to The TinkerPop!

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc46d649/docs/src/tutorials/getting-started/index.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/tutorials/getting-started/index.asciidoc b/docs/src/tutorials/getting-started/index.asciidoc
new file mode 100644
index 0000000..8787e57
--- /dev/null
+++ b/docs/src/tutorials/getting-started/index.asciidoc
@@ -0,0 +1,571 @@
+////
+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]
+
+Getting Started
+===============
+
+link:http://tinkerpop.com[Apache TinkerPop] is an open source Graph Computing Framework. Within itself, TinkerPop
+represents a large collection of capabilities and technologies and, in its wider ecosystem, an additionally extended
+world of link:http://tinkerpop.incubator.apache.org/#graph-systems[third-party contributed] graph libraries and
+systems. TinkerPop's ecosystem can appear complex to newcomers of all experience, especially when glancing at the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/index.html[reference documentation] for the first time.
+
+So, where do you get started with TinkerPop? How do you dive in quickly and get productive? Well - Gremlin, the
+most recognizable citizen of The TinkerPop, is here to help with this thirty minute tutorial. That's right - in just
+thirty short minutes, you too can be fit to start building graph applications with TinkerPop. Welcome to _The
+TinkerPop Workout - by Gremlin_!
+
+image::gremlin-gym.png[width=1024]
+
+The First Five Minutes
+----------------------
+
+It is quite possible to learn a lot in just five minutes with TinkerPop, but before doing so, a proper introduction of
+your trainer is in order. Meet Gremlin!
+
+image:gremlin-standing.png[width=125]
+
+Gremlin helps you navigate the vertices and edges of a graph. He is essentially your query language to graph
+databases, as link:http://sql2gremlin.com/[SQL] is the query language to relational databases. To tell Gremlin how
+he should "traverse" the graph (i.e. what you want your query to do) you need a way to provide him commands in the
+language he understands - and, of course, that language is called "Gremlin". For this task, you need one of
+TinkerPop's most important tools: link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#gremlin-console[The Gremlin Console].
+
+Download the console, unpackage it and start it:
+
+[source,text]
+----
+$ curl -L -O https://www.apache.org/dist/incubator/tinkerpop/x.y.z/apache-gremlin-console-x.y.z-bin.zip
+$ unzip apache-gremlin-console-x.y.z-bin.zip
+$ cd apache-gremlin-console-x.y.z-bin.zip
+$ bin/gremlin.sh
+
+         \,,,/
+         (o o)
+-----oOOo-(3)-oOOo-----
+plugin activated: tinkerpop.server
+plugin activated: tinkerpop.utilities
+plugin activated: tinkerpop.tinkergraph
+gremlin>
+----
+
+TIP: Windows users may use the included `bin/gremlin.bat` file to start the Gremlin Console.
+
+The Gremlin Console is a link:http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop[REPL environment],
+which provides a nice way to learn Gremlin as you get immediate feedback for the code that you enter. This eliminates
+the more complex need to "create a project" to try things out. The console is not just for "getting started" however.
+You will find yourself using it for a variety of TinkerPop-related activities, such as loading data, administering
+graphs, working out complex traversals, etc.
+
+To get Gremlin to traverse a graph, you need a `Graph` instance, which holds the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_the_graph_structure[structure] and data of the
+graph. TinkerPop is a graph abstraction layer over different graph databases and different graph processors, so there
+are many `Graph` instances you can choose from to instantiate in the console. The best `Graph` instance to start with
+however is link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#tinkergraph-gremlin[TinkerGraph]. TinkerGraph
+is a fast, in-memory graph database with a small handful of configuration options, making it a good choice for beginners.
+
+TIP: TinkerGraph is not just a toy for beginners. It is useful in analyzing subgraphs taken from a large graph,
+working with a small static graph that doesn't change much, writing unit tests and other use cases where the graph
+can fit in memory.
+
+TIP: Resist the temptation to "get started" with more complex databases like link:http://thinkaurelius.github.io/titan/[Titan]
+or to delve into how to get link:http://tinkerpop.incubator.apache.org/docs/x.y.zg/#gremlin-server[Gremlin Server]
+working properly. Focusing on the basics, presented in this guide, builds a good foundation for all the other things
+TinkerPop offers.
+
+To make your process even easier, start with one of TinkerPop's "toy" graphs. These are "small" graphs designed to
+provide a quick start into querying. It is good to get familiar with them, as almost all TinkerPop documentation is based
+on them and when you need help and have to come to the link:http://groups.google.com/group/gremlin-users[mailing list],
+a failing example put in the context of the toy graphs can usually get you a fast answer to your problem.
+
+For your first graph, use the "Modern" graph which looks like this:
+
+image:tinkerpop-modern.png[width=500]
+
+It can be instantiated in the console this way:
+
+[gremlin-groovy]
+----
+graph = TinkerFactory.createModern()
+g = graph.traversal()
+----
+
+The first command creates a `Graph` instance named `graph`, which thus provides a reference to the data you want
+Gremlin to traverse. Unfortunately, just having `graph` doesn't provide Gremlin enough context to do his job. You
+also need something called a `TraversalSource`, which is generated by the second command. The `TraversalSource`
+provides additional information to Gremlin (such as the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#traversalstrategy[traversal strategies]
+to apply and the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#graphcomputer[traversal engine] to use) which
+provides him guidance on how to execute his trip around the `Graph`.
+
+With your `TraversalSource` `g` available it is now possible to ask Gremlin to traverse the `Graph`:
+
+[gremlin-groovy,modern]
+----
+g.V()    <1>
+g.V(1)    <2>
+g.V(1).values('name')    <3>
+g.V(1).outE('knows')    <4>
+g.V(1).outE('knows').inV().values('name')    <5>
+g.V(1).out('knows').values('name')    <6>
+g.V(1).out('knows').has('age', gt(30)).values('name')    <7>
+----
+
+<1> Get all the vertices in the `Graph`.
+<2> Get a vertex with the unique identifier of "1".
+<3> Get the value of the `name` property on vertex with the unique identifier of "1".
+<4> Get the edges with the label "knows" for the vertex with the unique identifier of "1".
+<5> Get the names of the people that the vertex with the unique identifier of "1" "knows".
+<6> Note that when one uses `outE().inV()` as shown in the previous command, this can be shortened to just `out()`
+(similar to `inE().inV()` and `in` for incoming edges).
+<7> Get the names of the people vertex "1" knows who are over the age of 30.
+
+IMPORTANT: A `Traversal` is essentially an `Iterator` so if you have code like `x = g.V()`, the `x` does not contain
+the results of the `g.V()` query.  Rather, that statement assigns an `Iterator` value to `x`. To get your results,
+you would then need to iterate through `x`. This understanding is *important* because in the context of the console
+typing `g.V()` instantly returns a value. The console does some magic for you by noticing that `g.V()` returns
+an `Iterator` and then automatically iterates the results. In short, when writing Gremlin outside of the console
+always remember that you must iterate your `Traversal` manually in some way for it to do anything.
+
+In this first five minutes with Gremlin, you've gotten the Gremlin Console installed, instantiated a `Graph` and
+`TraversalSource`, wrote some traversals and hopefully learned something about TinkerPop in general. You've only
+scratched the surface of what there is to know, but those accomplishments will help enable your understanding of the
+detailed sections to come.
+
+The Next Fifteen Minutes
+------------------------
+
+In the first five minutes of _The TinkerPop Workout - by Gremlin_, you learned some basics for traversing graphs. Of
+course, there wasn't much discussion about what a graph is. A graph is a collection of vertices (i.e. nodes, dots)
+and edges (i.e. relationships, lines), where a vertex is an entity which represents some domain object (e.g. a person,
+a place, etc.) and an edge represents the relationship between two vertices.
+
+image:modern-edge-1-to-3-1.png[width=300]
+
+The diagram above shows a graph with two vertices, one with a unique identifier of "1" and another with a unique
+identifier of "3". There is a edge connecting the two with a unique identifier of "9". It is important to consider
+that the edge has a direction which goes _out_ from vertex "1" and _in_ to vertex "3'.
+
+IMPORTANT: Most TinkerPop implementations do not allow for identifier assignment. They will rather assign
+their own identifiers and ignore assigned identifiers that you attempt to assign to them.
+
+A graph with elements that just have identifiers does not make for much of a database. To give some meaning to
+this basic structure, vertices and edges can each be given labels to categorize them.
+
+image:modern-edge-1-to-3-2.png[width=300]
+
+You can now see that a vertex "1" is a "person" and vertex "3" is a "software" vertex. They are joined by a "created"
+edge which allows you to see that a "person created software". The "label" and the "id" are reserved attributes of
+vertices and edges, but you can add your own arbitrary properties as well:
+
+image:modern-edge-1-to-3-3.png[width=325]
+
+This model is referred to as a _property graph_ and it provides a flexible and intuitive way in which to model your
+data.
+
+Creating a Graph
+^^^^^^^^^^^^^^^^
+
+As intuitive as it is to you, it is perhaps more intuitive to Gremlin himself, as vertices, edges and properties make
+up the very elements of his existence. It is indeed helpful to think of our friend, Gremlin, moving about a graph when
+developing traversals, as picturing his position as the link:http://tinkerpop.incubator.apache.org/docs/3.0.2-incubating/#_the_traverser[traverser]
+helps orient where you need him to go next. Let's use the two vertex, one edge graph we've been discussing above
+as an example. First, you need to create this graph:
+
+[gremlin-groovy]
+----
+graph = TinkerGraph.open()
+v1 = graph.addVertex(id, 1, label, "person", "name", "marko", "age", 29)
+v2 = graph.addVertex(id, 3, label, "software", "name", "lop", "lang", "java")
+v1.addEdge("created", v2, id, 9, "weight", 0.4)
+----
+
+There are a number of important things to consider in the above code. First, recall that `id` and `label` are
+"reserved" for special usage in TinkerPop. Those "keys" supplied to the creation method are statically imported to
+the console. You would normally refer to them as `T.id` and `T.label`.
+
+NOTE: The fully qualified name for `T` is `org.apache.tinkerpop.gremlin.structure.T`.
+
+Second, don't forget that you are working with TinkerGraph which allows for identifier assignment. That is _not_ the
+case with most graph databases.
+
+Finally, the label for an `Edge` is required and is thus part of the method signature of `addEdge()`. It is the first
+parameter supplied, followed by the `Vertex` to which `v1` should be connected. Therefore, this usage of `addEdge` is
+creating an edge that goes _out_ of `v1` and into `v2` with a label of "created".
+
+Graph Traversal - Staying Simple
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Now that Gremlin knows where the graph data is, you can ask him to get you some data from it by doing a traversal,
+which you can think of as executing some link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_the_graph_process[process]
+over the structure of the graph. We can form our question in English and then translate it to Gremlin. For this
+initial example, let's ask Gremlin: "What software has Marko created?"
+
+To answer this question, we would want Gremlin to:
+
+. Find "marko" in the graph
+. Walk along the "created" edges to "software" vertices
+. Select the "name" property of the "software" vertices
+
+The English-based steps above largely translate to Gremlin's position in the graph and to the steps we need to take
+to ask him to answer our question. By stringing these steps together, we form a `Traversal` or the sequence of programmatic
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#graph-traversal-steps[steps] Gremlin needs to perform
+in order to get you an answer.
+
+Let's start with finding "marko". This operation is a filtering step as it searches the full set of vertices to match
+those that have the "name" property value of "marko". This can be done with the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#has-step[has()] step as follows:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko')
+----
+
+NOTE: The variable `g` is the `TraversalSource`, which was introduced in the "The First Five Minutes". The
+`TraversalSource` is created with `graph.traversal()` and is the object used to spawn new traversals.
+
+We can picture this traversal in our little graph with Gremlin sitting on vertex "1".
+
+image:modern-edge-1-to-3-1-gremlin.png[width=325]
+
+When Gremlin is on a vertex or an edge, he has access to all the properties that are available to that element.
+
+IMPORTANT: The above query iterates all the vertices in the graph to get its answer. That's fine for our little example,
+but for multi-million or billion edge graphs that is a big problem. To solve this problem, you should look to use
+indices. TinkerPop does not provide an abstraction for index management. You should consult the documentation of the
+graph you have chosen and utilize its native API to create indices which will then speed up these types of lookups. Your
+traversals will remain unchanged however, as the indices will be used transparently at execution time.
+
+Now that Gremlin has found "marko", he can now consider the next step in the traversal where we ask him to "walk"
+along "created" edges to "software" vertices. As described earlier, edges have direction, so we have to tell Gremlin
+what direction to follow. In this case, we want him to traverse on outgoing edges from the "marko" vertex. For this,
+we use the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#vertex-steps[outE] step.
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').outE('created')
+----
+
+At this point, you can picture Gremlin moving from the "marko" vertex to the "created" edge.
+
+image:modern-edge-1-to-3-2-gremlin.png[width=325]
+
+To get to the vertex on the other end of the edge, you need to tell Gremlin to move from the edge to the incoming
+vertex with `inV()`.
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').outE('created').inV()
+----
+
+You can now picture Gremlin on the "software" vertex as follows:
+
+image:modern-edge-1-to-3-3-gremlin.png[width=325]
+
+As you are not asking Gremlin to do anything with the properties of the "created" edge, you can simplify the
+statement above with:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').out('created')
+----
+
+Finally, now that Gremlin has reached the "software that Marko created", he has access to the properties of the
+"software" vertex and you can therefore ask Gremlin to extract the value of the "name" property as follows:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').out('created').values('name')
+----
+
+You should now be able to see the connection Gremlin has to the structure of the graph and how Gremlin maneuvers from
+vertices to edges and so on. Your ability to string together steps to ask Gremlin to do more complex things, depends
+on your understanding of these basic concepts.
+
+Graph Traversal - Increasing Complexity
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Armed with the knowledge from the previous section, let's ask Gremlin to perform some more difficult traversal tasks.
+There's not much more that can be done with the "baby" graph we had, so let's return to the "modern" toy graph from
+the "five minutes section". Recall that you can create this `Graph` and establish a `TraversalSource` with:
+
+[gremlin-groovy]
+----
+graph = TinkerFactory.createModern()
+g = graph.traversal()
+----
+
+Earlier we'd used the `has()` step to tell Gremlin how to find the "marko" vertex. Let's look at some other ways to
+use `has()`. What if we wanted Gremlin to find the "age" values of both "vadas" and "marko"? In this case we could
+use the `within` comparator with `has()` as follows:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name',within('vadas','marko')).values('age')
+----
+
+It is worth noting that `within` is statically imported from `P` to the Gremlin Console (much like `T` is, as described
+earlier).
+
+NOTE: The fully qualified name for `P` is `org.apache.tinkerpop.gremlin.process.traversal.P`.
+
+If we wanted to ask Gremlin the average age of "vadas" and "marko" we could use the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#mean-step[mean()] step as follows:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name',within('vadas','marko')).values('age').mean()
+----
+
+Another method of filtering is seen in the use of the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#where-step[where]
+step. We know how to find the "software" that "marko" created:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').out('created')
+----
+
+image:gremlin-on-software-vertex.png[width=350,float=right] Let's extend on that query to try to learn who "marko"
+collaborates with when it comes to the software he created. In other words, let's try to answer the question of: "Who
+are the people that marko develops software with?" To do that, we should first picture Gremlin where we left him in
+the previous query.  He was standing on the "software" vertex. To find out who "created" that "software", we need to
+have Gremlin traverse back _in_ along the "created" edges to find the "person" vertices tied to it.
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').out('created').in('created').values('name')
+----
+
+So that's nice, we can see that "peter", "josh" and "marko" are both responsible for creating "lop". Of course, we already
+know about the involvement of "marko" and it seems strange to say that "marko" collaborates with himself, so excluding
+"marko" from the results seems logical. The following traversal handles that exclusion:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').as('exclude').out('created').in('created').where(neq('exclude')).values('name')
+----
+
+We made two additions to the traversal to make it exclude "marko" from the results. First, we added the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#as-step[as()] step. The `as()` step is not really a "step",
+but a "step modulator" - something that adds features to a step or the traversal. Here, the `as('exclude')` labels
+the `has()` step with the name "exclude" and all values that pass through that step are held in that label for later
+use. In this case, the "marko" vertex is the only vertex to pass through that point, so it is held in "exclude".
+
+The other addition that was made was the `where()` step which is a filter step like `has()`. The `where()` is
+positioned after the `in()` step that has "person" vertices, which means that the `where()` filter is occurring
+on the list of "marko" collaborators. The `where()` specifies that the "person" vertices passing through it should
+not equal (i.e. `neq()`) the contents of the "exclude" label. As it just contains the "marko" vertex, the `where()`
+filters out the "marko" that we get when we traverse back _in_ on the "created" edges.
+
+You will find many uses of `as()`. Here it is in combination with link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#select-step[select]:
+
+[gremlin-groovy,modern]
+----
+g.V().as('a').out().as('b').out().as('c').select('a','b','c')
+----
+
+In the above example, we tell Gremlin to iterate through all vertices and traverse _out_ twice from each. Gremlin
+will label each vertex in that path with "a", "b" and "c", respectively. We can then use `select` to extract the
+contents of that label.
+
+Another common but important step is the link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#group-step[group()]
+step and its related step modulator called link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#by-step[by()]. If
+we wanted to ask Gremlin to group all the vertices in the graph by their vertex label we could do:
+
+[gremlin-groovy,modern]
+----
+g.V().group().by(label)
+----
+
+The use of `by()` here provides the mechanism by which to do the grouping. In this case, we've asked Gremlin to
+use the `label` (which, again, is an automatic static import from `T` in the console). We can't really tell much
+about our distribution though because we just have vertex unique identifiers as output. To make that nicer we
+could ask Gremlin to get us the value of the "name" property from those vertices, by supplying another `by()`
+modulator to `group()` to transform the values.
+
+[gremlin-groovy,modern]
+----
+g.V().group().by(label).by('name')
+----
+
+In this section, you have learned a bit more about what property graphs are and how Gremlin interacts with them.
+You also learned how to envision Gremlin moving about a graph and how to use some of the more complex, but commonly
+utilized traversal steps. You are now ready to think about TinkerPop in terms of its wider applicability to
+graph computing.
+
+The Final Ten Minutes
+---------------------
+
+In these final ten minutes of _The TinkerPop Workout - by Gremlin_ we'll look at TinkerPop from a higher level and
+introduce different features of the stack in order to orient you with what it offers. In this way, you can
+identify areas of interest and dig into the details from there.
+
+Why TinkerPop?
+^^^^^^^^^^^^^^
+
+image:provider-integration.png[float=right,width=350] The goal of TinkerPop, as a Graph Computing Framework, is to make it
+easy for developers to create graph applications by providing APIs and tools that simplify their endeavors. One of
+the fundamental aspects to what TinkerPop offers in this area lies in the fact that TinkerPop is an abstraction layer
+over different graph databases and different graph processors. As an abstraction layer, TinkerPop provides a way to
+avoid vendor lock-in to a specific database or processor. This capability provides immense value to developers who
+are thus afforded options in their architecture and development because:
+
+* They can try different implementations using the same code to decide which is best for their environment.
+* They can grow into a particular implementation if they so desire - start with a graph that is designed to scale
+within a single machine and then later switch to a graph that is designed to scale horizontally.
+* They can feel more confident in graph technology choices, as advances in the state of different provider
+implementations are behind TinkerPop APIs, which open the possibility to switch providers with limited impact.
+
+TinkerPop has always had the vision of being an abstraction over different graph databases. That much
+is not new and dates back to TinkerPop 1.x. It is in TinkerPop 3.x however that we see the introduction of the notion
+that TinkerPop is also an abstraction over different graph processors like link:http://spark.apache.org[Spark] and
+link:http://giraph.apache.org/[Giraph]. The scope of this tutorial does not permit it to delve into
+"graph processors", but the short story is that the same Gremlin statement we wrote in the examples above can be
+executed to run in distributed fashion over Spark or Hadoop. The changes required to the code to do this are not
+in the traversal itself, but in the definition of the `TraversalSource`. You can again see why we encourage, graph
+operations to be executed through that class as opposed to just using `Graph`. You can read more about these
+features in this section on link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#hadoop-gremlin[hadoop-gremlin].
+
+TIP: To maintain an abstraction over `Graph` creation use `GraphFactory.open()` to construct new instances. See
+the documentation for individual `Graph` implementations to learn about the configuration options to provide.
+
+Loading Data
+^^^^^^^^^^^^
+
+image:gremlin-to-the-7.png[width=100,float=left] There are many strategies for getting data into your graph. As you are just
+getting started, let's look the more simple methods aimed at "smaller" graphs. A "small" graph, in this context, is
+one that has less than ten million edges. The most direct way to load this data is to write a Groovy script that can
+be executed in the Gremlin Console, a tool that you should be well familiar with at this point. For our example, let's
+use the link:http://snap.stanford.edu/data/wiki-Vote.html[Wikipedia Vote Network] data set which contains 7,115
+vertices and 103,689 edges.
+
+[source,text]
+----
+$ curl -L -O http://snap.stanford.edu/data/wiki-Vote.txt.gz
+$ gunzip wiki-Vote.txt.gz
+----
+
+The data is contained in a tab-delimited structure where vertices are Wikipedia users and edges from one user to
+another implies a "vote" relationship. Here is the script to parse the file and generate the `Graph` instance using
+TinkerGraph:
+
+[source,groovy]
+----
+graph = TinkerGraph.open()
+graph.createIndex('userId', Vertex.class) <1>
+
+g = graph.traversal()
+
+getOrCreate = { id ->
+  g.V().has('userId', id).tryNext().orElseGet{ g.addV('userId', id).next() }
+}
+
+new File('wiki-Vote.txt').eachLine {
+  if (!it.startsWith("#")){
+    (fromVertex, toVertex) = it.split('\t').collect(getOrCreate) <2>
+    fromVertex.addEdge('votesFor', toVertex)
+  }
+}
+----
+
+<1> To ensure fast lookups of vertices, we need an index. The `createIndex()` method is a method native to
+TinkerGraph. Please consult your graph databases documentation for their index creation approaches.
+<2> We are iterating each line of the `wiki-Vote.txt` file and this line splits the line on the delimiter, then
+uses some neat Groovy syntax to apply the `getOrCreate()` function to each of the two `userId` fields encountered in
+the line and stores those vertices in the `fromVertex` and `toVertex` variables respectively.
+
+NOTE: While this is a tab-delimited structure, this same pattern can be applied
+to any data source you require and Groovy tends to have nice libraries that can help making working with data
+link:http://thinkaurelius.com/2013/02/04/polyglot-persistence-and-query-with-gremlin/[quite enjoyable].
+
+WARNING: Take care if using a `Graph` implementation that supports
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#transactions[transactions]. As TinkerGraph does not, there is
+no need to `commit()`.  If your `Graph` does support transactions, intermediate commits during load will need to be
+applied.
+
+To load larger data sets you should read about the
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#bulkloadervertexprogram[BulkLoaderVertexProgram] (BLVP), which
+provides a generalized method for loading graphs of virtually any size.
+
+Gremlin Server
+^^^^^^^^^^^^^^
+
+image:gremlin-server-protocol.png[width=325,float=right] link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#gremlin-server[Gremlin Server]
+provides a way to remotely execute Gremlin scripts against one or more `Graph` instances hosted within it. It does
+this by exposing different endpoints, such as link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_rest[REST]
+and link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_java[websockets], which allow a request
+containing a Gremlin script to be processed with results returned.
+
+[source,text]
+----
+$ curl -L -O https://www.apache.org/dist/incubator/tinkerpop/x.y.z/apache-gremlin-server-x.y.z-bin.zip
+$ unzip apache-gremlin-server-x.y.z-bin.zip
+$ cd apache-gremlin-server-x.y.z-bin.zip
+$ bin/gremlin-server.sh conf/gremlin-server-modern.yaml
+[INFO] GremlinServer -
+         \,,,/
+         (o o)
+-----oOOo-(3)-oOOo-----
+
+[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-rest-modern.yaml
+...
+[INFO] GremlinServer$1 - Channel started at port 8182.
+----
+
+[source,text]
+$ curl -X POST -d "{\"gremlin\":\"g.V(x).out().values('name')\", \"language\":\"gremlin-groovy\", \"bindings\":{\"x\":1}}" "http://localhost:8182"
+
+[source,json]
+----
+{
+    "requestId": "abe3be05-1e86-481a-85e0-c59ad8a37c6b",
+    "status": {
+        "message": "",
+        "code": 200,
+        "attributes": {}
+    },
+    "result": {
+        "data": [
+            "lop",
+            "vadas",
+            "josh"
+        ],
+        "meta": {}
+    }
+}
+----
+
+IMPORTANT: Take careful note of the use of "bindings" in the arguments on the request. These are variables that are
+applied to the script on execution and is essentially a way to parameterize your scripts. This "parameterization" is
+critical to link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_best_practices[performance].  Whenever
+possible, parameterize your queries.
+
+As mentioned earlier, Gremlin Server can also be configured with a websockets endpoint. This endpoint has an
+embedded link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_developing_a_driver[subprotocol] that allow a
+compliant driver to communicate with it.  TinkerPop supplies a
+link:http://tinkerpop.incubator.apache.org/docs/x.y.z/#_connecting_via_java[reference driver] written in Java, but
+there are drivers developed by third-parties for other link:http://tinkerpop.incubator.apache.org/#graph-libraries[languages]
+such as Python, Javascript, etc. Gremlin Server therefore represents the method by which non-JVM languages can
+interact with TinkerPop.
+
+Conclusion
+^^^^^^^^^^
+
+...and that is the end of _The TinkerPop Workout - by Gremlin_. You are hopefully feeling more confident in your
+TinkerPop skills and have a good overview of what the stack has to offer, as well as some entry points to further
+research within the reference documentation. Welcome to The TinkerPop!

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc46d649/docs/src/upgrade-release-3.0.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade-release-3.0.x-incubating.asciidoc b/docs/src/upgrade-release-3.0.x-incubating.asciidoc
deleted file mode 100644
index 4bb1473..0000000
--- a/docs/src/upgrade-release-3.0.x-incubating.asciidoc
+++ /dev/null
@@ -1,180 +0,0 @@
-////
-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.
-////
-
-TinkerPop 3.0.0
-===============
-
-image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/static/images/gremlin-hindu.png[width=225]
-
-*A Gremlin Rāga in 7/16 Time*
-
-TinkerPop 3.0.2
----------------
-
-*Release Date: October 19, 2015*
-
-Please see the link:https://github.com/apache/incubator-tinkerpop/blob/3.0.2-incubating/CHANGELOG.asciidoc#tinkerpop-302-release-date-october-19-2015[changelog] for a complete list of all the modifications that are part of this release.
-
-Upgrading for Users
-~~~~~~~~~~~~~~~~~~~
-
-BulkLoaderVertexProgram (BLVP)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-`BulkLoaderVertexProgram` now supports arbitrary inputs (i addition to `HadoopGraph`, which was already supported in
-version 3.0.1-incubating). It can now also read from any TP3 enabled graph, like `TinkerGraph`
-or `Neo4jGraph`.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-814[TINKERPOP3-319],
-link:http://tinkerpop.incubator.apache.org/docs/3.0.2-incubating/#bulkloadervertexprogram[Reference Documentation - BLVP]
-
-TinkerGraph
-^^^^^^^^^^^
-
-TinkerGraph can now be configured to support persistence, where TinkerGraph will try to load a graph from a specified
-location and calls to `close()` will save the graph data to that location.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-828[TINKERPOP3-828],
-link:http://tinkerpop.incubator.apache.org/docs/3.0.2-incubating/#_configuration[Reference Documentation - TinkerGraph]
-
-Gremlin Driver and Server
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-There were a number of fixes to `gremlin-driver` that prevent protocol desynchronization when talking to Gremlin
-Server.
-
-On the Gremlin Server side, Websocket sub-protocol introduces a new "close" operation to explicitly close sessions.
-Prior to this change, sessions were closed in a more passive fashion (i.e. session timeout).  There were also so
-bug fixes around the protocol as it pertained to third-party drivers (e.g. python) using JSON for authentication.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-814[TINKERPOP3-814],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-816[TINKERPOP3-816],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-817[TINKERPOP3-817],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-855[TINKERPOP3-855],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-870[TINKERPOP3-870],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-877[TINKERPOP3-877]
-
-Upgrading for Providers
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Graph Driver Providers
-^^^^^^^^^^^^^^^^^^^^^^
-
-Gremlin Server close Operation
-++++++++++++++++++++++++++++++
-
-It is important to note that this feature of the sub-protocol applies to the `SessionOpProcessor` (i.e. for
-session-based requests).  Prior to this change, there was no way to explicitly close a session.  Sessions would get
-closed by the server after timeout of activity.  This new "op" gives drivers the ability to close the session
-explicitly and as needed.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-849[TINKERPOP3-849],
-link:http://tinkerpop.incubator.apache.org/docs/3.0.2-incubating/#_opprocessors_arguments[Reference Documentation - OpProcessor]
-
-TinkerPop 3.0.1
----------------
-
-*Release Date: September 2, 2015*
-
-Please see the link:https://github.com/apache/incubator-tinkerpop/blob/3.0.1-incubating/CHANGELOG.asciidoc#tinkerpop-301-release-date-september-2-2015[changelog] for a complete list of all the modifications that are part of this release.
-
-Upgrading for Users
-~~~~~~~~~~~~~~~~~~~
-
-Gremlin Server
-^^^^^^^^^^^^^^
-
-Gremlin Server now supports a link:https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL-based] 
-(Simple Authentication and Security Layer) authentication model and a default `SimpleAuthenticator` which implements 
-the `PLAIN` SASL mechanism (i.e. plain text) to authenticate requests.  This gives Gremlin Server some basic security 
-capabilities, especially when combined with its built-in SSL feature.
-
-There have also been changes in how global variable bindings in Gremlin Server are established via initialization
-scripts.  The initialization scripts now allow for a `Map` of values that can be returned from those scripts.  
-That `Map` will be used to set global bindings for the server. See this 
-link:https://github.com/apache/incubator-tinkerpop/blob/3.0.1-incubating/gremlin-server/scripts/generate-modern.groovy[sample script] 
-for an example.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-576[TINKERPOP3-576] 
-
-Neo4j
-^^^^^
-
-Problems related to using `:install` to get the Neo4j plugin operating in Gremlin Console on Windows have been 
-resolved.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-804[TINKERPOP3-804]
-
-Upgrading for Providers
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Graph System Providers
-^^^^^^^^^^^^^^^^^^^^^^
-
-GraphFactoryClass Annotation
-++++++++++++++++++++++++++++
-
-Providers can consider the use of the new `GraphFactoryClass` annotation to specify the factory class that `GraphFactory` will use to open a new `Graph` instance. This is an optional feature and will generally help implementations that have an interface extending `Graph`.  If that is the case, then this annotation can be used in the following fashion:
-
-[source,java]
-----
-@GraphFactory(MyGraphFactory.class)
-public interface MyGraph extends Graph{
-}
-----
-
-`MyGraphFactory` must contain the static `open` method that is normally expected by `GraphFactory`.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-778[TINKERPOP3-778]
-
-GraphProvider.Descriptor Annotation
-+++++++++++++++++++++++++++++++++++
-
-There was a change that affected providers who implemented `GraphComputer` related tests such as the `ProcessComputerSuite`.  If the provider runs those tests, then edit the `GraphProvider` implementation for those suites to include the `GraphProvider.Descriptor` annotation as follows:
-
-[source,java]
-----
-@GraphProvider.Descriptor(computer = GiraphGraphComputer.class)
-public final class HadoopGiraphGraphProvider extends HadoopGraphProvider {
-
-    public GraphTraversalSource traversal(final Graph graph) {
-        return GraphTraversalSource.build().engine(ComputerTraversalEngine.build().computer(GiraphGraphComputer.class)).create(graph);
-    }
-}
-----
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-690[TINKERPOP3-690] for more information.
-
-Semantics of Transaction.close()
-++++++++++++++++++++++++++++++++
-
-There were some adjustments to the test suite with respect to how `Transaction.close()` was being validated.  For most providers, this will generally mean checking `OptOut` annotations for test renaming problems.  The error that occurs when running the test suite should make it apparent that a test name is incorrect in an `OptOut` if there are issues there.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-764[TINKERPOP3-764] for more information.
-
-Graph Driver Providers
-^^^^^^^^^^^^^^^^^^^^^^
-
-Authentication
-++++++++++++++
-
-Gremlin Server now supports SASL-based authentication.  By default, Gremlin Server is not configured with
-authentication turned on and authentication is not required, so existing drivers should still work without any
-additional change.  Drivers should however consider implementing this feature as it is likely that many users will
-want the security capabilities that it provides.
-
-See: link:http://tinkerpop.incubator.apache.org/docs/3.0.1-incubating/#_authentication[Reference Documentation - Gremlin Server Authentication]

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc46d649/docs/src/upgrade-release-3.1.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade-release-3.1.x-incubating.asciidoc b/docs/src/upgrade-release-3.1.x-incubating.asciidoc
deleted file mode 100644
index 32d23f0..0000000
--- a/docs/src/upgrade-release-3.1.x-incubating.asciidoc
+++ /dev/null
@@ -1,322 +0,0 @@
-////
-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.
-////
-
-TinkerPop 3.1.0
-===============
-
-image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/static/images/gremlin-gangster.png[width=225]
-
-*A 187 On The Undercover Gremlinz*
-
-TinkerPop 3.1.0
----------------
-
-*Release Date: November 16, 2015*
-
-Please see the link:https://github.com/apache/incubator-tinkerpop/blob/3.1.0-incubating/CHANGELOG.asciidoc#tinkerpop-310-release-date-november-16-2015[changelog] for a complete list of all the modifications that are part of this release.
-
-Additional upgrade information can be found here:
-
-* <<_tinkerpop_3_0_2,TinkerPop 3.0.2>>
-* <<_tinkerpop_3_0_1,TinkerPop 3.0.1>>
-
-Upgrading for Users
-~~~~~~~~~~~~~~~~~~~
-
-Shading Jackson
-^^^^^^^^^^^^^^^
-
-The Jackson library is now shaded to `gremlin-shaded`, which will allow Jackson to version independently without
-breaking compatibility with dependent libraries or with those who depend on TinkerPop.  The downside is that if a
-library depends on TinkerPop and uses the Jackson classes, those classes will no longer exist with the standard
-Jackson package naming.  They will have to shifted as follows:
-
-* `org.objenesis` becomes `org.apache.tinkerpop.shaded.objenesis`
-* `com.esotericsoftware.minlog` becomes `org.apache.tinkerpop.shaded.minlog`
-* `com.fasterxml.jackson` becomes `org.apache.tinkerpop.shaded.jackson`
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-835[TINKERPOP3-835]
-
-PartitionStrategy and VertexProperty
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-`PartitionStrategy` now supports partitioning within `VertexProperty`.  The `Graph` needs to be able to support
-meta-properties for this feature to work.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-333[TINKERPOP3-333]
-
-Gremlin Server and Epoll
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Gremlin Server provides a configuration option to turn on support for Netty
-link:http://netty.io/wiki/native-transports.html[native transport] on Linux, which has been shown to help improve
-performance.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-901[TINKERPOP3-901]
-
-Rebindings Deprecated
-^^^^^^^^^^^^^^^^^^^^^
-
-The notion of "rebindings" has been deprecated in favor of the term "aliases".  Alias is a better and more intuitive
-term than rebindings which should make it easier for newcomers to understand what they are for.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-913[TINKERPOP3-913],
-link:http://tinkerpop.incubator.apache.org/docs/3.1.0-incubating/#_aliases[Reference Documentation - Aliases]
-
-Configurable Driver Channelizer
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The Gremlin Driver now allows the `Channerlizer` to be supplied as a configuration, which means that custom
-implementations may be supplied.
-
-See: https://issues.apache.org/jira/browse/TINKERPOP3-680[TINKERPOP3-680]
-
-GraphSON and Strict Option
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The `GraphMLReader` now has a `strict` option on the `Builder` so that if a data type for a value is invalid in some
-way, GraphMLReader will simply skip that problem value. In that way, it is a bit more forgiving than before especially
-with empty data.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-756[TINKERPOP3-756]
-
-Transaction.close() Default Behavior
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The default behavior of `Transaction.close()` is to rollback the transaction.  This is in contrast to previous versions
-where the default behavior was commit.  Using rollback as the default should be thought of as a like a safer approach
-to closing where a user must now explicitly call `commit()` to persist their mutations.
-
-See link:https://issues.apache.org/jira/browse/TINKERPOP3-805[TINKERPOP3-805] for more information.
-
-ThreadLocal Transaction Settings
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The `Transaction.onReadWrite()` and `Transaction.onClose()` settings now need to be set for each thread (if another
-behavior than the default is desired). For gremlin-server users that may be changing these settings via scripts.
-If the settings are changed for a sessionless request they will now only apply to that one request. If the settings are
-changed for an in-session request they will now only apply to all future requests made in the scope of that session.
-
-See link:https://issues.apache.org/jira/browse/TINKERPOP3-885[TINKERPOP3-885]
-
-Hadoop-Gremlin
-^^^^^^^^^^^^^^
-
-* Hadoop1 is no longer supported. Hadoop2 is now the only supported Hadoop version in TinkerPop.
-* Spark and Giraph have been split out of Hadoop-Gremlin into their own respective packages (Spark-Gremlin and Giraph-Gremlin).
-* The directory where application jars are stored in HDFS is now `hadoop-gremlin-x.y.z-libs`.
-** This versioning is important so that cross-version TinkerPop use does not cause jar conflicts.
-
-See link:https://issues.apache.org/jira/browse/TINKERPOP3-616
-
-Spark-Gremlin
-^^^^^^^^^^^^^
-
-* Providers that wish to reuse a graphRDD can leverage the new `PersistedInputRDD` and `PersistedOutputRDD`.
-** This allows the graphRDD to avoid serialization into HDFS for reuse. Be sure to enabled persisted `SparkContext` (see documentation).
-
-See link:https://issues.apache.org/jira/browse/TINKERPOP3-868,
-link:https://issues.apache.org/jira/browse/TINKERPOP3-925
-
-TinkerGraph Serialization
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-TinkerGraph is serializable over Gryo, which means that it can shipped over the wire from Gremlin Server.  This
-feature can be useful when working with remote subgraphs.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-728[TINKERPOP3-728]
-
-Deprecation in TinkerGraph
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The `public static String` configurations have been renamed. The old `public static` variables have been deprecated.
-If the deprecated variables were being used, then convert to the replacements as soon as possible.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-926[TINKERPOP3-926]
-
-Deprecation in Gremlin-Groovy
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The closure wrappers classes `GFunction`, `GSupplier`, `GConsumer` have been deprecated. In Groovy, a closure can be
-specified using `as Function` and thus, these wrappers are not needed. Also, the `GremlinExecutor.promoteBindings()`
-method which was previously deprecated has been removed.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-879[TINKERPOP3-879],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-897[TINKERPOP3-897]
-
-Gephi Traversal Visualization
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The process for visualizing a traversal has been simplified.  There is no longer a need to "name" steps that will
-represent visualization points for Gephi.  It is possible to just "configure" a `visualTraversal` in the console:
-
-[source,text]
-gremlin> :remote config visualTraversal graph vg
-
-which creates a special `TraversalSource` from `graph` called `vg`.  The traversals created from `vg` can be used
-to `:submit` to Gephi.
-
-See: link:http://tinkerpop.incubator.apache.org/docs/3.1.0-SNAPSHOT/#gephi-plugin[Reference Documentation - Gephi]
-
-Alterations to GraphTraversal
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-There were a number of changes to `GraphTraversal`.  Many of the changes came by way of deprecation, but some semantics
-have changed as well:
-
-* `ConjunctionStrategy` has been renamed to `ConnectiveStrategy` (no other behaviors changed).
-* `ConjunctionP` has been renamed to `ConnectiveP` (no other behaviors changed).
-* `DedupBijectionStrategy` has been renamed (and made more effective) as `FilterRankingStrategy`.
-* The `GraphTraversal` mutation API has change significantly with all previous methods being supported but deprecated.
-** The general pattern used now is `addE('knows').from(select('a')).to(select('b')).property('weight',1.0)`.
-* The `GraphTraversal` sack API has changed with all previous methods being supported but deprecated.
-** The old `sack(mult,'weight')` is now `sack(mult).by('weight')`.
-* `GroupStep` has been redesigned such that there is now only a key- and value-traversal. No more reduce-traversal.
-** The previous `group()`-methods have been renamed to `groupV3d0()`. To immediately upgrade, rename all your `group()`-calls to `groupV3d0()`.
-** To migrate to the new `group()`-methods, what was `group().by('age').by(outE()).by(sum(local))` is now `group().by('age').by(outE().sum())`.
-* There was a bug in `fold()`, where if a bulked traverser was provided, the traverser was only represented once.
-** This bug fix might cause a breaking change to a user query if the non-bulk behavior was being counted on. If so, used `dedup()` prior to `fold()`.
-* Both `GraphTraversal().mapKeys()` and `GraphTraversal.mapValues()` has been deprecated.
-** Use `select(keys)` and `select(columns)`. However, note that `select()` will not unroll the keys/values. Thus, `mapKeys()` => `select(keys).unfold()`.
-* The data type of `Operator` enums will now always be the highest common data type of the two given numbers, rather than the data type of the first number, as it's been before.
-
-Aliasing Remotes in the Console
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The `:remote` command in Gremlin Console has a new `alias` configuration option.  This `alias` option allows
-specification of a set of key/value alias/binding pairs to apply to the remote.  In this way, it becomes possible
-to refer to a variable on the server as something other than what it is referred to for purpose of the submitted
-script.  For example once a `:remote` is created, this command:
-
-[source,text]
-:remote alias x g
-
-would allow "g" on the server to be referred to as "x".
-
-[source,text]
-:> x.E().label().groupCount()
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-914[TINKERPOP3-914]
-
-Upgrading for Providers
-~~~~~~~~~~~~~~~~~~~~~~~
-
-IMPORTANT: It is recommended that providers also review all the upgrade instructions specified for users. Many of the
-changes there may prove important for the provider's implementation.
-
-All providers should be aware that Jackson is now shaded to `gremlin-shaded` and could represent breaking change if
-there was usage of the dependency by way of TinkerPop, a direct dependency to Jackson may be required on the
-provider's side.
-
-Graph System Providers
-^^^^^^^^^^^^^^^^^^^^^^
-
-GraphStep Alterations
-+++++++++++++++++++++
-
-* `GraphStep` is no longer in `sideEffect`-package, but now in `map`-package as traversals support mid-traversal `V()`.
-* Traversals now support mid-traversal `V()`-steps. Graph system providers should ensure that a mid-traversal `V()` can leverage any suitable index.
-
-See link:https://issues.apache.org/jira/browse/TINKERPOP3-762
-
-Decomposition of AbstractTransaction
-++++++++++++++++++++++++++++++++++++
-
-The `AbstractTransaction` class has been abstracted into two different classes supporting two different modes of
-operation: `AbstractThreadLocalTransaction` and `AbstractThreadedTransaction`, where the former should be used when
-supporting `ThreadLocal` transactions and the latter for threaded transactions.  Of course, providers may still
-choose to build their own implementation on `AbstractTransaction` itself or simply implement the `Transaction`
-interface.
-
-The `AbstractTransaction` gains the following methods to potentially implement (though default implementations
-are supplied in `AbstractThreadLocalTransaction` and `AbstractThreadedTransaction`):
-
-* `doReadWrite` that should execute the read-write consumer.
-* `doClose` that should execute the close consumer.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-765[TINKERPOP3-765],
-link:https://issues.apache.org/jira/browse/TINKERPOP3-885[TINKERPOP3-885]
-
-Transaction.close() Default Behavior
-++++++++++++++++++++++++++++++++++++
-
-The default behavior for `Transaction.close()` is to rollback the transaction and is enforced by tests, which
-previously asserted the opposite (i.e. commit on close).  These tests have been renamed to suite the new semantics:
-
-* `shouldCommitOnCloseByDefault` became `shouldCommitOnCloseWhenConfigured`
-* `shouldRollbackOnCloseWhenConfigured` became `shouldRollbackOnCloseByDefault`
-
-If these tests were referenced in an `OptOut`, then their names should be updated.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-805[TINKERPOP3-805]
-
-Graph Traversal Updates
-+++++++++++++++++++++++
-
-There were numerous changes to the `GraphTraversal` API. Nearly all changes are backwards compatible with respective
-"deprecated" annotations. Please review the respective updates specified in the "Graph System Users" section.
-
-* `GraphStep` is no longer in `sideEffect` package. Now in `map` package.
-* Make sure mid-traversal `GraphStep` calls are folding `HasContainers` in for index-lookups.
-* Think about copying `TinkerGraphStepStrategyTest` for your implementation so you know folding is happening correctly.
-
-Element Removal
-+++++++++++++++
-
-`Element.Exceptions.elementAlreadyRemoved` has been deprecated and test enforcement for consistency have been removed.
- Providers are free to deal with deleted elements as they see fit.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-297[TINKERPOP3-297]
-
-VendorOptimizationStrategy Rename
-+++++++++++++++++++++++++++++++++
-
-The `VendorOptimizationStrategy` has been renamed to `ProviderOptimizationStrategy`.  This renaming is consistent
-with revised terminology for what were formerly referred to as "vendors".
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-876[TINKERPOP3-876]
-
-GraphComputer Updates
-+++++++++++++++++++++
-
-`GraphComputer.configure(String key, Object value)` is now a method (with default implementation).
-This allows the user to specify engine-specific parameters to the underlying OLAP system. These parameters are not intended
-to be cross engine supported. Moreover, if there are not parameters that can be altered (beyond the standard `GraphComputer`
-methods), then the provider's `GraphComputer` implementation should simply return and do nothing.
-
-Driver Providers
-^^^^^^^^^^^^^^^^
-
-Aliases Parameter
-+++++++++++++++++
-
-The "rebindings" argument to the "standard" `OpProcessor` has been renamed to "aliases". While "rebindings" is still
-supported it is recommended that the upgrade to "aliases" be made as soon as possible as support will be removed in
-the future.  Gremlin Server will not accept both parameters at the same time - a request must contain either one
-parameter or the other if either is supplied.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-913[TINKERPOP3-913]
-
-ThreadLocal Transaction Settings
-++++++++++++++++++++++++++++++++
-
-If a driver configures the `Transaction.onReadWrite()` or `Transaction.onClose()` settings, note that these settings no
-longer apply to all future requests. If the settings are changed for a sessionless request they will only apply to
-that one request. If the settings are changed from an in-session request they will only apply to all future requests
-made in the scope of that session.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP3-885[TINKERPOP3-885]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc46d649/docs/src/upgrade.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade.asciidoc b/docs/src/upgrade.asciidoc
deleted file mode 100644
index 86dd6b6..0000000
--- a/docs/src/upgrade.asciidoc
+++ /dev/null
@@ -1,39 +0,0 @@
-////
-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]
-
-:toc-position: left
-
-TinkerPop Upgrade Information
-=============================
-
-This document helps users of TinkerPop to understand the changes that come with each software release.  It outlines
-new features, how to resolve breaking changes and other information specific to a release.  This document is useful
-to end-users who are building applications on TinkerPop, but it is equally useful to TinkerPop providers, who
-build libraries and other systems on the the core APIs and protocols that TinkerPop exposes.
-
-These providers include:
-
-* Graph System Provider
-** Graph Database Provider
-** Graph Processor Provider
-* Graph Driver Provider
-* Graph Language Provider
-
-include::upgrade-release-3.1.x-incubating.asciidoc[]
-
-include::upgrade-release-3.0.x-incubating.asciidoc[]
\ No newline at end of file