You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/06/19 19:31:02 UTC

[2/2] incubator-tinkerpop git commit: WhereSteps work natively inside MatchStep as the fabled 'predicate traversal.' MatchWhereStrategy is now called MatchPredicateStrategy and it supports the folding of where() and the pulling out of has() for index loo

WhereSteps work natively inside MatchStep as the fabled 'predicate traversal.' MatchWhereStrategy is now called MatchPredicateStrategy and it supports the folding of where() and the pulling out of has() for index lookups. Added more information to the MatchStep docs. MatchStep is looking really really good now.


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

Branch: refs/heads/master
Commit: 2e3a25c318136b7f6c1aec5fae2c0c1b950fb3f9
Parents: 4740a0d
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Fri Jun 19 11:30:54 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Fri Jun 19 11:30:54 2015 -0600

----------------------------------------------------------------------
 docs/src/the-traversal.asciidoc                 |  37 +++---
 .../process/traversal/TraversalStrategies.java  |   4 +-
 .../traversal/step/filter/WhereStep.java        |  29 ++++-
 .../process/traversal/step/map/MatchStep.java   |  19 ++-
 .../optimization/MatchPredicateStrategy.java    | 111 ++++++++++++++++
 .../optimization/MatchWhereStrategy.java        |  95 --------------
 .../process/traversal/util/TraversalHelper.java |   8 ++
 .../MatchPredicateStrategyTest.java             | 127 ++++++++++++++++++
 .../optimization/MatchWhereStrategyTest.java    | 129 -------------------
 .../traversal/step/map/GroovyMatchTest.groovy   |   8 +-
 .../process/traversal/step/map/MatchTest.java   |  30 ++---
 11 files changed, 327 insertions(+), 270 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/docs/src/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/the-traversal.asciidoc b/docs/src/the-traversal.asciidoc
index 28f02c8..1b77f62 100644
--- a/docs/src/the-traversal.asciidoc
+++ b/docs/src/the-traversal.asciidoc
@@ -706,7 +706,7 @@ WARNING: The anonymous traversal of `local()` processes the current object "loca
 Match Step
 ~~~~~~~~~~
 
-The `match()`-step (*map*) provides a more link:http://en.wikipedia.org/wiki/Declarative_programming[declarative] form of graph querying based on the notion of link:http://en.wikipedia.org/wiki/Pattern_matching[pattern matching]. With `match()`, the user provides a collection of "traversal fragments," called patterns, that have variables defined that much hold true throughout the duration of the `match()`. When a traverser is in `match()`, a registered `MatchAlgorithm` analyzes the current state of the traverser (i.e. its history based on its <<path-data-structure,path data>>) and returns a traversal-pattern that the traverser should try next. The default `MatchAlgorithm` provided is called `CountMatchAlgorithm` and it dynamically revises the pattern execution plan to ensure that patterns that do the most filtering (i.e. largest set reduction) occur first. For very large graphs, where the developer is uncertain of the statistics of the graph (e.g. how many `knows`-edges vs. `worksFo
 r`-edges exist in the graph), it is advantageous to use `match()`, as an optimal plan will be determined automatically. Furthermore, some queries are much easier to express via `match()` than with single-path traversals.
+The `match()`-step (*map*) provides a more link:http://en.wikipedia.org/wiki/Declarative_programming[declarative] form of graph querying based on the notion of link:http://en.wikipedia.org/wiki/Pattern_matching[pattern matching]. With `match()`, the user provides a collection of "traversal fragments," called patterns, that have variables defined that much hold true throughout the duration of the `match()`. When a traverser is in `match()`, a registered `MatchAlgorithm` analyzes the current state of the traverser (i.e. its history based on its <<path-data-structure,path data>>) and returns a traversal-pattern that the traverser should try next. The default `MatchAlgorithm` provided is `CountMatchAlgorithm` and it dynamically revises the pattern execution plan by sorting the patterns according to their filtering capabilities (i.e. largest set reduction patterns execute first). For very large graphs, where the developer is uncertain of the statistics of the graph (e.g. how many `knows`
 -edges vs. `worksFor`-edges exist in the graph), it is advantageous to use `match()`, as an optimal plan will be determined automatically. Furthermore, some queries are much easier to express via `match()` than with single-path traversals.
 
     "Who created a project named 'lop' that was also created by someone who is 29 years old? Return the two creators."
 
@@ -809,7 +809,7 @@ g.V().as('a').out().as('b'). <1>
           __.as('a').out('knows').as('b'),
           __.as('b').in().count().as('c').and().as('c').is(gt(2))  <5>
         )
-    )
+    ).select('a','b','c').by('name').by('name').by() <6>
 ----
 
 <1> A standard, labeled traversal can come prior to `match()`.
@@ -817,6 +817,7 @@ g.V().as('a').out().as('b'). <1>
 <3> It is possible to use <<a-note-on-barrier-steps,barrier steps>> though they are computed locally to the pattern (as one would expect).
 <4> It is possible to nest `and()`- and `or()`-steps for conjunction matching.
 <5> Both infix and prefix conjunction notation is supported.
+<6> The bound values are of different types -- vertex ("a"), vertex ("b"), long ("c").
 
 [[using-where-with-match]]
 Using Where with Match
@@ -832,26 +833,30 @@ g.V().match('a',
           where('a', neq('c')).select('a','c').by('name')
 ----
 
-The `where()`-step can take either a `P`-predicate (example above) or a `Traversal` (example below). Using `MatchWhereStrategy`, `where()`-clauses can be automatically folded into `match()` and thus, subject to the query optimizer within `match()`-step.
+The `where()`-step can take either a `P`-predicate (example above) or a `Traversal` (example below). Using `MatchPredicateStrategy`, `where()`-clauses can be automatically folded into `match()` and thus, subject to the query optimizer within `match()`-step.
 
 [gremlin-groovy,modern]
 ----
 traversal = g.V().match('a',
+                    __.as('a').has(label,'person'), <1>
                     __.as('a').out('created').as('b'),
                     __.as('b').in('created').as('c')).
-                      where(__.as('a').out('knows').as('c')). <1>
-                      select('a','c').by('name'); null <2>
-traversal.toString() <3>
-traversal <4> <5>
-traversal.toString() <6>
-----
-
-<1> A `where()`-step with a traversal containing variable bindings declared in `match()`.
-<2> A useful trick to ensure that that the traversal is not iterated by Gremlin Console.
-<3> The string representation of the traversal prior to its strategies being applied.
-<4> The Gremlin Console will automatically iterate anything that is an iterator or is iterable.
-<5> Both marko and josh are co-developers and marko knows josh.
-<6> The string representation of the traversal after the strategies have been applied (and thus, `where()` is folded into `match()`)
+                      where(__.as('a').out('knows').as('c')). <2>
+                      select('a','c').by('name'); null <3>
+traversal.toString() <4>
+traversal <5> <6>
+traversal.toString() <7>
+----
+
+<1> Any `has()`-step traversal patterns that start with the match-key are pulled out of `match()` to enable the vendor to leverage the filter for index lookups.
+<2> A `where()`-step with a traversal containing variable bindings declared in `match()`.
+<3> A useful trick to ensure that that the traversal is not iterated by Gremlin Console.
+<4> The string representation of the traversal prior to its strategies being applied.
+<5> The Gremlin Console will automatically iterate anything that is an iterator or is iterable.
+<6> Both marko and josh are co-developers and marko knows josh.
+<7> The string representation of the traversal after the strategies have been applied (and thus, `where()` is folded into `match()`)
+
+IMPORTANT: A `where()`-step is a filter and thus, variables within a `where()` clause are not globally bound to the path of the traverser in `match()`. As such, `where()`-steps in `match()` are used for filtering, not binding.
 
 [[max-step]]
 Max Step

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 857b3c3..fb35ead 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -26,7 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Adja
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.DedupBijectionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchWhereStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserGeneratorFactory;
@@ -204,7 +204,7 @@ public interface TraversalStrategies extends Serializable, Cloneable {
                     AdjacentToIncidentStrategy.instance(),
                     DedupBijectionStrategy.instance(),
                     IdentityRemovalStrategy.instance(),
-                    MatchWhereStrategy.instance(),
+                    MatchPredicateStrategy.instance(),
                     RangeByIsCountStrategy.instance(),
                     ComputerVerificationStrategy.instance());
             //LambdaRestrictionStrategy.instance(),

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
index fe11135..fa986bf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
@@ -60,7 +60,7 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
         super(whereTraversal);
         this.scope = scope;
         this.startKey = startKey.orElse(null);
-        if(null != this.startKey) this.scopeKeys.add(this.startKey);
+        if (null != this.startKey) this.scopeKeys.add(this.startKey);
         this.predicate = (P) predicate;
         this.selectKeys = new ArrayList<>();
         this.whereTraversal = null;
@@ -89,8 +89,8 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
                 throw new IllegalArgumentException("The start step of a where()-traversal can only have one label: " + startStep);
             final String label = startStep.getLabels().iterator().next();
             this.scopeKeys.add(label);
-            TraversalHelper.replaceStep(startStep, (Step) new WhereStartStep(whereTraversal, label), whereTraversal);
-        } else if(!whereTraversal.getEndStep().getLabels().isEmpty()){                    // out().as("a").. traversals
+            TraversalHelper.replaceStep(startStep, new WhereStartStep(whereTraversal, label), whereTraversal);
+        } else if (!whereTraversal.getEndStep().getLabels().isEmpty()) {                    // out().as("a").. traversals
             TraversalHelper.insertBeforeStep(new WhereStartStep(whereTraversal, null), (Step) startStep, whereTraversal);
         }
         //// END STEP to WhereEndStep
@@ -122,6 +122,19 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
             predicate.setValue(this.getScopeValueByKey(Pop.last, selectKeysIterator.next(), traverser));
     }
 
+    public Optional<P<?>> getPredicate() {
+        return Optional.ofNullable(this.predicate);
+    }
+
+    public Optional<String> getStartKey() {
+        return Optional.ofNullable(this.startKey);
+    }
+
+    public void removeStartKey() {
+        this.selectKeys.remove(this.startKey);
+        this.startKey = null;
+    }
+
     @Override
     protected boolean filter(final Traverser.Admin<S> traverser) {
         if (null != this.whereTraversal)
@@ -160,7 +173,7 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ this.scope.hashCode() ^ (null == this.predicate ? this.whereTraversal.hashCode() : this.predicate.hashCode());
+        return super.hashCode() ^ this.scope.hashCode() ^ (null == this.startKey ? "null".hashCode() : this.startKey.hashCode()) ^ (null == this.predicate ? this.whereTraversal.hashCode() : this.predicate.hashCode());
     }
 
     @Override
@@ -189,7 +202,7 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
 
     public static class WhereStartStep<S> extends MapStep<S, Object> implements Scoping {
 
-        private final String selectKey;
+        private String selectKey;
         private Scope scope = Scope.global;
 
         public WhereStartStep(final Traversal.Admin traversal, final String selectKey) {
@@ -229,6 +242,10 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
             this.scope = scope;
         }
 
+        public void removeScopeKey() {
+            this.selectKey = null;
+        }
+
         @Override
         public Set<String> getScopeKeys() {
             return null == this.selectKey ? Collections.emptySet() : Collections.singleton(this.selectKey);
@@ -278,7 +295,7 @@ public final class WhereStep<S> extends FilterStep<S> implements TraversalParent
 
         @Override
         public void setScope(Scope scope) {
-            this.scope = scope;
+            //this.scope = scope;
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
index e80bf5b..c33b796 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
@@ -109,6 +109,18 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
             final String label = startStep.getLabels().iterator().next();
             this.matchStartLabels.add(label);
             TraversalHelper.replaceStep((Step) matchTraversal.getStartStep(), new MatchStartStep(matchTraversal, label), matchTraversal);
+        } else if (startStep instanceof WhereStep) {
+            final WhereStep<?> whereStep = (WhereStep<?>) startStep;
+            if (whereStep.getStartKey().isPresent()) {           // where('a',eq('b')) --> as('a').where(eq('b'))
+                TraversalHelper.insertBeforeStep(new MatchStartStep(matchTraversal, whereStep.getStartKey().get()), (Step) whereStep, matchTraversal);
+                whereStep.removeStartKey();
+            } else if (!whereStep.getLocalChildren().isEmpty()) { // where(as('a').out()) -> as('a').where(out())
+                final Traversal.Admin<?, ?> whereTraversal = whereStep.getLocalChildren().get(0);
+                if (whereTraversal.getStartStep() instanceof WhereStep.WhereStartStep && !((WhereStep.WhereStartStep) whereTraversal.getStartStep()).getScopeKeys().isEmpty()) {
+                    TraversalHelper.insertBeforeStep(new MatchStartStep(matchTraversal, ((WhereStep.WhereStartStep<?>) whereTraversal.getStartStep()).getScopeKeys().iterator().next()), (Step) whereStep, matchTraversal);
+                    ((WhereStep.WhereStartStep) whereTraversal.getStartStep()).removeScopeKey();
+                }
+            }
         } else {
             TraversalHelper.insertBeforeStep(new MatchStartStep(matchTraversal, null), (Step) matchTraversal.getStartStep(), matchTraversal);
         }
@@ -131,6 +143,11 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         }
     }
 
+    public void addGlobalChild(final Traversal.Admin<?, ?> globalChildTraversal) {
+        this.configureStartAndEndSteps(globalChildTraversal);
+        this.matchTraversals.add(this.integrateChild(globalChildTraversal));
+    }
+
     @Override
     public void removeGlobalChild(final Traversal.Admin<?, ?> globalChildTraversal) {
         this.matchTraversals.remove(globalChildTraversal);
@@ -263,7 +280,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
     @Override
     protected Iterator<Traverser<Map<String, E>>> computerAlgorithm() throws NoSuchElementException {
         final Traverser.Admin traverser = this.starts.next();
-        if(!traverser.path().hasLabel(this.getId()))
+        if (!traverser.path().hasLabel(this.getId()))
             traverser.path().addLabel(this.getId()); // so the traverser never returns to this branch ever again
         if (hasMatched(this.conjunction, traverser)) {
             traverser.setStepId(this.getNextStep().getId());

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategy.java
new file mode 100644
index 0000000..694ac5a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategy.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * MatchWhereStrategy will fold any post-<code>where()</code> step that maintains a traversal constraint into <code>match()</code>.
+ * {@link MatchStep} is intelligent with traversal constraint applications and thus, can more efficiently use the constraint of {@link WhereStep}.
+ * <p/>
+ * <p/>
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @example <pre>
+ * __.match(a,b).where(c)            // is replaced by __.match(a,b,c)
+ * __.match(a,b).select().where(c)  // is replaced by __.match(a,b,c).select()
+ * </pre>
+ */
+public final class MatchPredicateStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+    private static final MatchPredicateStrategy INSTANCE = new MatchPredicateStrategy();
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>();
+
+    static {
+        PRIORS.add(IdentityRemovalStrategy.class);
+    }
+
+    private MatchPredicateStrategy() {
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        if (!TraversalHelper.hasStepOfClass(MatchStep.class, traversal))
+            return;
+
+        TraversalHelper.getStepsOfClass(MatchStep.class, traversal).forEach(matchStep -> {
+            Step<?, ?> nextStep = matchStep.getNextStep();
+            while (nextStep instanceof WhereStep || nextStep instanceof SelectStep || nextStep instanceof SelectOneStep) {   // match().select().where() --> match(where()).select()
+                if (nextStep instanceof WhereStep) {
+                    traversal.removeStep(nextStep);
+                    matchStep.addGlobalChild(new DefaultTraversal<>().addStep(nextStep));
+                    nextStep = matchStep.getNextStep();
+                } else if (nextStep.getLabels().isEmpty()) {
+                    nextStep = nextStep.getNextStep();
+                } else
+                    break;
+            }
+            if (matchStep.getStartKey().isPresent()) {
+                ((MatchStep<?, ?>) matchStep).getGlobalChildren().stream().collect(Collectors.toList()).forEach(matchTraversal -> {   // match('a',has(key,value)) --> as('a').has(key,value).match()
+                    if (matchTraversal.getStartStep() instanceof MatchStep.MatchStartStep) {
+                        ((MatchStep.MatchStartStep) matchTraversal.getStartStep()).getSelectKey().ifPresent(selectKey -> {
+                            if (selectKey.equals(matchStep.getStartKey().get()) &&
+                                    !(matchStep.getPreviousStep() instanceof EmptyStep) &&
+                                    !matchTraversal.getSteps().stream()
+                                            .filter(step -> !(step instanceof MatchStep.MatchStartStep) &&
+                                                    !(step instanceof MatchStep.MatchEndStep) &&
+                                                    !(step instanceof HasStep))
+                                            .findAny()
+                                            .isPresent()) {
+                                matchStep.removeGlobalChild(matchTraversal);
+                                matchTraversal.removeStep(0);                                     // remove XMatchStartStep
+                                matchTraversal.removeStep(matchTraversal.getSteps().size() - 1);    // remove XMatchEndStep
+                                TraversalHelper.insertTraversal(matchStep.getPreviousStep(), matchTraversal, traversal);
+                            }
+                        });
+                    }
+                });
+            }
+        });
+    }
+
+    public static MatchPredicateStrategy instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return PRIORS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategy.java
deleted file mode 100644
index 8774212..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategy.java
+++ /dev/null
@@ -1,95 +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.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * MatchWhereStrategy will fold any post-<code>where()</code> step that maintains a traversal constraint into <code>match()</code>.
- * {@link MatchStep} is intelligent with traversal constraint applications and thus, can more efficiently use the constraint of {@link WhereStep}.
- * <p/>
- * <p/>
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @example <pre>
- * __.match(a,b).where(c)            // is replaced by __.match(a,b,c)
- * __.match(a,b).select().where(c)  // is replaced by __.match(a,b,c).select()
- * </pre>
- */
-public final class MatchWhereStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
-
-    private static final MatchWhereStrategy INSTANCE = new MatchWhereStrategy();
-    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>();
-
-    static {
-        PRIORS.add(IdentityRemovalStrategy.class);
-    }
-
-    private MatchWhereStrategy() {
-    }
-
-    @Override
-    public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!TraversalHelper.hasStepOfClass(MatchStep.class, traversal))
-            return;
-
-        // pull out match(as("a").has().has()) to has().has().match() in order to allow vendors to leverages has-containers for index lookups
-        TraversalHelper.getStepsOfClass(MatchStep.class, traversal).forEach(matchStep -> {
-            if (matchStep.getStartKey().isPresent()) {
-                ((MatchStep<?, ?>) matchStep).getGlobalChildren().stream().collect(Collectors.toList()).forEach(conjunction -> {
-                    if (conjunction.getStartStep() instanceof MatchStep.MatchStartStep) {
-                        ((MatchStep.MatchStartStep) conjunction.getStartStep()).getSelectKey().ifPresent(selectKey -> {
-                            if (selectKey.equals(matchStep.getStartKey().get()) && !conjunction.getSteps().stream()
-                                    .filter(step -> !(step instanceof MatchStep.MatchStartStep) &&
-                                            !(step instanceof MatchStep.MatchEndStep) &&
-                                            !(step instanceof HasStep))
-                                    .findAny()
-                                    .isPresent() && !(matchStep.getPreviousStep() instanceof EmptyStep)) {
-                                matchStep.removeGlobalChild(conjunction);
-                                conjunction.removeStep(0);                                     // remove XMatchStartStep
-                                conjunction.removeStep(conjunction.getSteps().size() - 1);    // remove XMatchEndStep
-                                TraversalHelper.insertTraversal(matchStep.getPreviousStep(), conjunction, traversal);
-                            }
-                        });
-                    }
-                });
-            }
-        });
-    }
-
-    public static MatchWhereStrategy instance() {
-        return INSTANCE;
-    }
-
-    @Override
-    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
-        return PRIORS;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 7d476d8..af9db5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
@@ -53,6 +54,13 @@ public final class TraversalHelper {
 
     private static boolean isLocalStarGraph(final Traversal.Admin<?, ?> traversal, char state) {
         for (final Step step : traversal.getSteps()) {
+            if (step instanceof RepeatStep &&
+                    ((RepeatStep<?>) step).getGlobalChildren().stream()
+                            .flatMap(t -> t.getSteps().stream())
+                            .filter(temp -> temp instanceof VertexStep)
+                            .findAny()
+                            .isPresent())  // TODO: is this sufficient?
+                return false;
             if (step instanceof PropertiesStep && state == 'u')
                 return false;
             else if (step instanceof VertexStep) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategyTest.java
new file mode 100644
index 0000000..0ade3ac
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchPredicateStrategyTest.java
@@ -0,0 +1,127 @@
+/*
+ *
+ *  * 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.
+ *
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(Enclosed.class)
+public class MatchPredicateStrategyTest {
+
+    @RunWith(Parameterized.class)
+    public static class StandardTest extends AbstractMatchWhereStrategyTest {
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Iterable<Object[]> data() {
+            return generateTestParameters();
+        }
+
+        @Parameterized.Parameter(value = 0)
+        public Traversal original;
+
+        @Parameterized.Parameter(value = 1)
+        public Traversal optimized;
+
+        @Before
+        public void setup() {
+            this.traversalEngine = mock(TraversalEngine.class);
+            when(this.traversalEngine.getType()).thenReturn(TraversalEngine.Type.STANDARD);
+        }
+
+        @Test
+        public void shouldApplyStrategy() {
+            doTest(original, optimized);
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class ComputerTest extends AbstractMatchWhereStrategyTest {
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Iterable<Object[]> data() {
+            return generateTestParameters();
+        }
+
+        @Parameterized.Parameter(value = 0)
+        public Traversal original;
+
+        @Parameterized.Parameter(value = 1)
+        public Traversal optimized;
+
+        @Before
+        public void setup() {
+            this.traversalEngine = mock(TraversalEngine.class);
+            when(this.traversalEngine.getType()).thenReturn(TraversalEngine.Type.COMPUTER);
+        }
+
+        @Test
+        public void shouldApplyStrategy() {
+            doTest(original, optimized);
+        }
+    }
+
+    private static abstract class AbstractMatchWhereStrategyTest {
+
+        protected TraversalEngine traversalEngine;
+
+        void applyMatchWhereStrategy(final Traversal traversal) {
+            final TraversalStrategies strategies = new DefaultTraversalStrategies();
+            strategies.addStrategies(MatchPredicateStrategy.instance(), IdentityRemovalStrategy.instance());
+
+            traversal.asAdmin().setStrategies(strategies);
+            traversal.asAdmin().setEngine(this.traversalEngine);
+            traversal.asAdmin().applyStrategies();
+
+        }
+
+        public void doTest(final Traversal traversal, final Traversal optimized) {
+            applyMatchWhereStrategy(traversal);
+            assertEquals(optimized, traversal);
+        }
+
+        static Iterable<Object[]> generateTestParameters() {
+
+            return new ArrayList<>();
+           /* return Arrays.asList(new Traversal[][]{
+                    {__.match("a", __.as("a").out().as("b")).where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b"), __.as("b").out("knows"))},
+                    {__.match("a", __.as("a").out().as("b")).select().where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b"), __.as("b").out("knows")).select()},
+                    {__.match("a", __.as("a").out().as("b")).select().as("x").where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b")).select().as("x").where(__.as("b").out("knows"))}
+            });*/
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategyTest.java
deleted file mode 100644
index b3ddd1f..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MatchWhereStrategyTest.java
+++ /dev/null
@@ -1,129 +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.
- *
- */
-
-package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.runners.Enclosed;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@RunWith(Enclosed.class)
-public class MatchWhereStrategyTest {
-
-    @RunWith(Parameterized.class)
-    public static class StandardTest extends AbstractMatchWhereStrategyTest {
-
-        @Parameterized.Parameters(name = "{0}")
-        public static Iterable<Object[]> data() {
-            return generateTestParameters();
-        }
-
-        @Parameterized.Parameter(value = 0)
-        public Traversal original;
-
-        @Parameterized.Parameter(value = 1)
-        public Traversal optimized;
-
-        @Before
-        public void setup() {
-            this.traversalEngine = mock(TraversalEngine.class);
-            when(this.traversalEngine.getType()).thenReturn(TraversalEngine.Type.STANDARD);
-        }
-
-        @Test
-        public void shouldApplyStrategy() {
-            doTest(original, optimized);
-        }
-    }
-
-    @RunWith(Parameterized.class)
-    public static class ComputerTest extends AbstractMatchWhereStrategyTest {
-
-        @Parameterized.Parameters(name = "{0}")
-        public static Iterable<Object[]> data() {
-            return generateTestParameters();
-        }
-
-        @Parameterized.Parameter(value = 0)
-        public Traversal original;
-
-        @Parameterized.Parameter(value = 1)
-        public Traversal optimized;
-
-        @Before
-        public void setup() {
-            this.traversalEngine = mock(TraversalEngine.class);
-            when(this.traversalEngine.getType()).thenReturn(TraversalEngine.Type.COMPUTER);
-        }
-
-        @Test
-        public void shouldApplyStrategy() {
-            doTest(original, optimized);
-        }
-    }
-
-    private static abstract class AbstractMatchWhereStrategyTest {
-
-        protected TraversalEngine traversalEngine;
-
-        void applyMatchWhereStrategy(final Traversal traversal) {
-            final TraversalStrategies strategies = new DefaultTraversalStrategies();
-            strategies.addStrategies(MatchWhereStrategy.instance(), IdentityRemovalStrategy.instance());
-
-            traversal.asAdmin().setStrategies(strategies);
-            traversal.asAdmin().setEngine(this.traversalEngine);
-            traversal.asAdmin().applyStrategies();
-
-        }
-
-        public void doTest(final Traversal traversal, final Traversal optimized) {
-            applyMatchWhereStrategy(traversal);
-            assertEquals(optimized, traversal);
-        }
-
-        static Iterable<Object[]> generateTestParameters() {
-
-            return new ArrayList<>();
-           /* return Arrays.asList(new Traversal[][]{
-                    {__.match("a", __.as("a").out().as("b")).where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b"), __.as("b").out("knows"))},
-                    {__.match("a", __.as("a").out().as("b")).select().where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b"), __.as("b").out("knows")).select()},
-                    {__.match("a", __.as("a").out().as("b")).select().as("x").where(__.as("b").out("knows")), __.match("a", __.as("a").out().as("b")).select().as("x").where(__.as("b").out("knows"))}
-            });*/
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
index a2f945c..bf95cf2 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
@@ -78,12 +78,12 @@ public abstract class GroovyMatchTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_repeatXoutX_timesX2XX_selectXnameX() {
+        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_whereXrepeatXoutX_timesX2XXX() {
             TraversalScriptHelper.compute("""
                 g.V.match('a',
                     __.as('a').out('created').has('name', 'lop').as('b'),
                     __.as('b').in('created').has('age', 29).as('c'),
-                    __.as('c').repeat(__.out).times(2)).select.by('name')
+                    __.as('c').where(repeat(__.out).times(2)))
             """, g)
         }
 
@@ -174,13 +174,13 @@ public abstract class GroovyMatchTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXnameX() {
+        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_select() {
             TraversalScriptHelper.compute("""
                 g.V.match("a",
                     __.as("a").out("created").has("name", "lop").as("b"),
                     __.as("b").in("created").has("age", 29).as("c"))
                     .where(__.as("c").repeat(__.out).times(2))
-                    .select.by('name')
+                    .select
             """, g)
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/2e3a25c3/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
index 660ffa2..0b7ac65 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
@@ -66,9 +66,9 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
     public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_b__a_repeatXoutX_timesX2XX_selectXab_nameX();
 
     // illustrates early deduplication in "predicate" traversals
-    public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_repeatXoutX_timesX2XX_selectXnameX();
+    public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_whereXrepeatXoutX_timesX2XXX();
 
-    public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXnameX();
+    public abstract Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_select();
 
     public abstract Traversal<Vertex, String> get_g_V_out_out_matchXa_0created_b__b_0knows_cX_selectXcX_outXcreatedX_name();
 
@@ -196,20 +196,16 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    // TODO: DEBATABLE RESULTS
     public void g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXnameX() throws Exception {
         final List<Traversal<Vertex, Map<String, String>>> traversals = Arrays.asList(
-                get_g_V_matchXa_created_lop_b__b_0created_29_c__c_repeatXoutX_timesX2XX_selectXnameX());
-        //get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXnameX());  // todo: predicate traversals are local traversals?
+                get_g_V_matchXa_created_lop_b__b_0created_29_c__c_whereXrepeatXoutX_timesX2XXX(),
+        get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_select());
         traversals.forEach(traversal -> {
             printTraversalForm(traversal);
             checkResults(makeMapList(3,
-                    "a", "marko", "b", "lop", "c", "marko",
-                    "a", "marko", "b", "lop", "c", "marko",
-                    "a", "josh", "b", "lop", "c", "marko",
-                    "a", "josh", "b", "lop", "c", "marko",
-                    "a", "peter", "b", "lop", "c", "marko",
-                    "a", "peter", "b", "lop", "c", "marko"), traversal);
+                    "a",  convertToVertex(graph, "marko"), "b", convertToVertex(graph, "lop"), "c", convertToVertex(graph, "marko"),
+                    "a",  convertToVertex(graph, "josh"), "b", convertToVertex(graph, "lop"), "c",  convertToVertex(graph, "marko"),
+                    "a",  convertToVertex(graph, "peter"), "b", convertToVertex(graph, "lop"), "c",  convertToVertex(graph, "marko")), traversal);
         });
     }
 
@@ -317,8 +313,8 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(GRATEFUL)
     public void g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_d__c_sungBy_d__d_hasXname_GarciaXX() throws Exception {
         final List<Traversal<Vertex, Map<String, Vertex>>> traversals = Arrays.asList(
-                get_g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_d__c_sungBy_d__d_hasXname_GarciaXX());
-        //get_g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_dX_whereXc_sungBy_dX_whereXd_hasXname_GarciaXX());  // TODO: the where() is trying to get Garcia's name. Why is ComputerVerificationStrategy allowing this?
+                get_g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_d__c_sungBy_d__d_hasXname_GarciaXX(),
+        get_g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_dX_whereXc_sungBy_dX_whereXd_hasXname_GarciaXX());  // TODO: the where() is trying to get Garcia's name. Why is ComputerVerificationStrategy allowing this?
 
         traversals.forEach(traversal -> {
             printTraversalForm(traversal);
@@ -426,19 +422,19 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_repeatXoutX_timesX2XX_selectXnameX() {
+        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_c__c_whereXrepeatXoutX_timesX2XXX() {
             return g.V().match("a",
                     as("a").out("created").has("name", "lop").as("b"),
                     as("b").in("created").has("age", 29).as("c"),
-                    __.<Vertex>as("c").repeat(out()).times(2)).<String>select().by("name");
+                    as("c").where(repeat(out()).times(2)));
         }
 
         @Override
-        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXnameX() {
+        public Traversal<Vertex, Map<String, String>> get_g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_select() {
             return g.V().match("a",
                     as("a").out("created").has("name", "lop").as("b"),
                     as("b").in("created").has("age", 29).as("c"))
-                    .where(__.<Vertex>as("c").repeat(out()).times(2)).<String>select().by("name");
+                    .where(__.<Vertex>as("c").repeat(out()).times(2)).select();
         }
 
         @Override