This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new 0e83640927 Show optimization strategies firing in the Unnecessary
Steps recipe
0e83640927 is described below
commit 0e8364092720935e6a9158cede1706aca3ace4d7
Author: Stephen Mallette <[email protected]>
AuthorDate: Wed Aug 5 17:51:39 2026 +0000
Show optimization strategies firing in the Unnecessary Steps recipe
The Unnecessary Steps anti-patterns recipe stated that TinkerPop rewrites
these
traversals automatically but offered no way to confirm it, never named the
strategies involved, and gave no pointer to further reading. Add a runnable
explain() example on the original queries so the rewrites are visible, name
the
IncidentToAdjacentStrategy and AdjacentToIncidentStrategy strategies that
perform them, and cross-reference the explain() and profile() steps and the
traversal strategies section of the reference documentation.
Assisted-by: Kiro:claude-opus-4.8
---
docs/src/recipes/anti-patterns.asciidoc | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/docs/src/recipes/anti-patterns.asciidoc
b/docs/src/recipes/anti-patterns.asciidoc
index 2734999d65..b4683a0cce 100644
--- a/docs/src/recipes/anti-patterns.asciidoc
+++ b/docs/src/recipes/anti-patterns.asciidoc
@@ -154,6 +154,32 @@ g.V().hasLabel("person").out("created").dedup()
g.V().hasLabel("software").inE("created").count()
----
+These rewrites can be observed rather than taken on faith. The
`explain()`-step reports how a traversal is compiled once
+all registered traversal strategies have been applied, which makes the
optimizations visible. Running `explain()` on the
+two original (unoptimized) queries shows the relevant strategies firing:
+
+[gremlin-groovy,modern]
+----
+g.V().hasLabel("person").outE("created").inV().dedup().explain()
+g.V().hasLabel("software").inE("created").outV().count().explain()
+----
+
+Each row of the explanation is the state of the traversal after the strategy
named in the first column has been applied.
+The second column is the strategy category: [D]ecoration, [O]ptimization,
[P]rovider optimization,
+[F]inalization, or [V]erification. In the first explanation, the
`IncidentToAdjacentStrategy` (an optimization)
+is the row that folds `outE("created").inV()` into a single `out("created")`
step, matching the manual rewrite shown
+above. In the second explanation two strategies cooperate. The
`IncidentToAdjacentStrategy` first collapses
+`inE("created").outV()` to `in("created")`, and then the
`AdjacentToIncidentStrategy` rewrites that counted adjacency
+back onto the incident edges so that the vertex step becomes an edge step
again, which is the `inE("created").count()`
+form. The `Final Traversal` line at the bottom of each explanation is the
execution plan that actually runs.
+
+Further detail on these execution plans, including how to measure their
runtime effect rather than only inspect them, is
+available in the
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#explain-step[`explain()`]
and
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#profile-step[`profile()`]
steps, as well as the
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#traversalstrategy[traversal
strategies] section of the Reference
+Documentation, which catalogs the full set of optimizations
(`IncidentToAdjacentStrategy` and
+`AdjacentToIncidentStrategy` among them).
+
Another anti-pattern that is commonly seen is the chaining of `where()`-steps
using predicates. Consider the following traversal:
[gremlin-groovy,modern]