diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java index 142c95620b..7c61b5463e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java @@ -67,6 +67,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep; @@ -171,6 +172,10 @@ public static void extractHasContainer(HugeGraphStep newStep, step = step.getNextStep(); if (step instanceof HasStep) { HasContainerHolder holder = (HasContainerHolder) step; + if (followedByMatchStep(step) && + hasIndexRequiredPredicate(holder)) { + break; + } for (HasContainer has : holder.getHasContainers()) { if (!GraphStep.processHasContainerIds(newStep, has)) { newStep.addHasContainer(has); @@ -182,6 +187,37 @@ public static void extractHasContainer(HugeGraphStep newStep, } while (step instanceof HasStep || step instanceof NoOpBarrierStep); } + private static boolean followedByMatchStep(Step step) { + Step next = step.getNextStep(); + while (next instanceof HasStep || next instanceof NoOpBarrierStep) { + next = next.getNextStep(); + } + return next instanceof MatchStep; + } + + private static boolean hasIndexRequiredPredicate(HasContainerHolder holder) { + for (HasContainer has : holder.getHasContainers()) { + if (hasIndexRequiredPredicate(has)) { + return true; + } + } + return false; + } + + private static boolean hasIndexRequiredPredicate(HasContainer has) { + List> predicates = new ArrayList<>(); + collectPredicates(predicates, ImmutableList.of(has.getPredicate())); + for (P pred : predicates) { + BiPredicate bp = pred.getBiPredicate(); + if (bp == Compare.neq || + bp == Compare.gt || bp == Compare.gte || + bp == Compare.lt || bp == Compare.lte) { + return true; + } + } + return false; + } + public static void extractHasContainer(HugeVertexStep newStep, Traversal.Admin traversal) { Step step = newStep; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java index fdfc9d2e44..77450b71ae 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java @@ -48,6 +48,33 @@ private void initGraph() { commitTx(); } + private void initMatchNoIndexSchema() { + SchemaManager schema = graph().schema(); + schema.propertyKey("vp2").asBoolean().create(); + schema.propertyKey("vp3").asLong().create(); + schema.propertyKey("vp4").asText().create(); + schema.vertexLabel("vl1").properties("vp2", "vp4") + .nullableKeys("vp2", "vp4").create(); + schema.vertexLabel("vl0").properties("vp3") + .nullableKeys("vp3").create(); + schema.edgeLabel("el1").link("vl1", "vl0").create(); + } + + private void initMatchNoIndexGraph() { + Vertex v1 = graph().addVertex(T.label, "vl1", "vp2", true, + "vp4", "foo"); + Vertex v2 = graph().addVertex(T.label, "vl1", "vp2", false, + "vp4", "J2O"); + Vertex v3 = graph().addVertex(T.label, "vl0", + "vp3", 4592737712018141719L); + Vertex v4 = graph().addVertex(T.label, "vl0", + "vp3", 4592737712018141717L); + + v1.addEdge("el1", v3); + v2.addEdge("el1", v4); + commitTx(); + } + @Test public void testWhereCountLtNegativeIsAlwaysFalse() { this.initSchema(); @@ -125,4 +152,32 @@ public void testWhereCountGteNegativeDoesNotBuildInvalidRange() { Assert.assertEquals(4L, count); } + + @Test + public void testMatchWithNoIndexConditionMatchesDirectTraversal() { + this.initMatchNoIndexSchema(); + this.initMatchNoIndexGraph(); + + long direct = graph().traversal().V() + .has("vp4", P.neq("J2O")) + .has("vl1", "vp2", P.gte(false)) + .has("vp2") + .has("vl0", "vp3", P.gt(4592737712018141718L)) + .out("el1") + .count().next(); + long viaMatch = graph().traversal().V() + .has("vp4", P.neq("J2O")) + .has("vl1", "vp2", P.gte(false)) + .match(__.as("start0") + .has("vp2") + .has("vl0", "vp3", + P.gt(4592737712018141718L)) + .repeat(__.out("el1")) + .times(1) + .as("m0")) + .select("m0").count().next(); + + Assert.assertEquals(0L, direct); + Assert.assertEquals(direct, viaMatch); + } }