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

[31/50] [abbrv] incubator-tinkerpop git commit: Neo4jGraphStep is now uses Neo4j schema indices appropriately. Much simpler Neo4jGraphStep without having to think about automatic indices.

Neo4jGraphStep is now uses Neo4j schema indices appropriately. Much simpler Neo4jGraphStep without having to think about automatic indices.


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

Branch: refs/heads/preprocessor
Commit: 50bd2973d81d1fd1d478da6ff565f841a542c48a
Parents: 486bc3b
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Sat May 30 13:45:40 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Sat May 30 13:45:40 2015 -0600

----------------------------------------------------------------------
 .../step/sideEffect/Neo4jGraphStep.java         | 111 +++++++------------
 .../gremlin/neo4j/structure/Neo4jGraph.java     |   1 +
 .../neo4j/AbstractNeo4jGraphProvider.java       |  28 +++++
 .../gremlin/neo4j/NativeNeo4jSuite.java         |   8 +-
 .../neo4j/structure/NativeNeo4jIndexTest.java   |  60 ++++++++++
 .../structure/NativeNeo4jStructureTest.java     |   2 -
 6 files changed, 137 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
index 949a22a..f274e32 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
@@ -20,30 +20,21 @@ package org.apache.tinkerpop.gremlin.neo4j.process.traversal.step.sideEffect;
 
 import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
 import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
-import org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait;
 import org.apache.tinkerpop.gremlin.process.traversal.Compare;
-import org.apache.tinkerpop.gremlin.process.traversal.Contains;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.javatuples.Pair;
-import org.neo4j.tinkerpop.api.Neo4jDirection;
-import org.neo4j.tinkerpop.api.Neo4jGraphAPI;
-import org.neo4j.tinkerpop.api.Neo4jNode;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
+import java.util.Optional;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -73,76 +64,56 @@ public final class Neo4jGraphStep<S extends Element> extends GraphStep<S> {
             return IteratorUtils.filter(graph.vertices(this.ids), vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers));
         ////// do index lookups //////
         graph.tx().readWrite();
-        // a label and a property
-        final Pair<String, HasContainer> labelHasPair = this.getHasContainerForLabelIndex();
-        if (null != labelHasPair)
-            return this.getVerticesUsingLabelAndProperty(labelHasPair.getValue0(), labelHasPair.getValue1())
-                    .filter(vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers)).iterator();
-        // only labels
-        final List<String> labels = this.getInternalLabels();
-        if (null != labels)
-            return this.getVerticesUsingOnlyLabels(labels).filter(vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers)).iterator();
-        // linear scan
-        return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers));
-    }
-
-
-    private Stream<Neo4jVertex> getVerticesUsingLabelAndProperty(final String label, final HasContainer hasContainer) {
-        final Neo4jGraph graph = (Neo4jGraph) this.getTraversal().getGraph().get();
-        final Iterable<Neo4jNode> iterator1 = graph.getBaseGraph().findNodes(label, hasContainer.getKey(), hasContainer.getValue());
-        final Iterable<Neo4jNode> iterator2 = graph.getBaseGraph().findNodes(hasContainer.getKey(), T.value.getAccessor(), hasContainer.getValue());
-        final Stream<Neo4jVertex> stream1 = IteratorUtils.stream(iterator1)
-                .filter(node -> ElementHelper.idExists(node.getId(), this.ids))
-                .map(node -> new Neo4jVertex(node, graph));
-        final Stream<Neo4jVertex> stream2 = IteratorUtils.stream(iterator2)
-                .filter(node -> ElementHelper.idExists(node.getId(), this.ids))
-                .filter(node -> node.getProperty(T.key.getAccessor()).equals(hasContainer.getKey()))
-                .map(node -> node.relationships(Neo4jDirection.INCOMING).iterator().next().start())
-                .map(node -> new Neo4jVertex(node, graph));
-        return Stream.concat(stream1, stream2);
-    }
-
-    private Stream<Neo4jVertex> getVerticesUsingOnlyLabels(final List<String> labels) {
-        final Neo4jGraph graph = (Neo4jGraph) this.getTraversal().getGraph().get();
-        final Predicate<Neo4jNode> nodePredicate = graph.getTrait().getNodePredicate();
-        return labels.stream()
-                .flatMap(label -> IteratorUtils.stream(graph.getBaseGraph().findNodes(label)))
-                .filter(node -> ElementHelper.idExists(node.getId(), this.ids))
-                .filter(nodePredicate)
-                .map(node -> new Neo4jVertex(node, graph));
-    }
-
-    private Pair<String, HasContainer> getHasContainerForLabelIndex() {
-        final Neo4jGraph graph = (Neo4jGraph) this.getTraversal().getGraph().get();
-        Neo4jGraphAPI baseGraph = graph.getBaseGraph();
-        for (final HasContainer hasContainer : this.hasContainers) {
-            if (hasContainer.getKey().equals(T.label.getAccessor()) && hasContainer.getBiPredicate().equals(Compare.eq)) {
-                if (baseGraph.hasSchemaIndex(
-                        (String) hasContainer.getValue(), hasContainer.getKey())) {
-                    return Pair.with((String) hasContainer.getValue(), hasContainer);
+        // get a label being search on
+        final Optional<String> label = this.hasContainers.stream()
+                .filter(hasContainer -> hasContainer.getKey().equals(T.label.getAccessor()))
+                .filter(hasContainer -> hasContainer.getPredicate().equals(Compare.eq))
+                .map(hasContainer -> (String) hasContainer.getValue())
+                .findAny();
+        if (label.isPresent()) {
+            // find a vertex by label and key/value
+            for (final HasContainer hasContainer : this.hasContainers) {
+                if (hasContainer.getPredicate().equals(Compare.eq)) {
+                    return IteratorUtils.filter(
+                            IteratorUtils.map(
+                                    graph.getBaseGraph().findNodes(label.get(), hasContainer.getKey(), hasContainer.getValue()).iterator(),
+                                    node -> new Neo4jVertex(node, graph)),
+                            vertex -> HasContainer.testAll(vertex, this.hasContainers));
+                }
+            }
+        } else {
+            // find a vertex by key/value
+            for (final HasContainer hasContainer : this.hasContainers) {
+                if (hasContainer.getPredicate().equals(Compare.eq)) {
+                    return IteratorUtils.filter(
+                            IteratorUtils.map(
+                                    graph.getBaseGraph().findNodes(hasContainer.getKey(), hasContainer.getValue()).iterator(),
+                                    node -> new Neo4jVertex(node, graph)),
+                            vertex -> HasContainer.testAll(vertex, this.hasContainers));
                 }
             }
         }
-        return null;
-    }
-
-    private List<String> getInternalLabels() {
-        for (final HasContainer hasContainer : this.hasContainers) {
-            if (hasContainer.getKey().equals(T.label.getAccessor()) && hasContainer.getBiPredicate().equals(Compare.eq))
-                return Arrays.asList(((String) hasContainer.getValue()));
-            else if (hasContainer.getKey().equals(T.label.getAccessor()) && hasContainer.getBiPredicate().equals(Contains.within))
-                return new ArrayList<>((Collection<String>) hasContainer.getValue());
+        if (label.isPresent()) {
+            // find a vertex by label
+            return IteratorUtils.filter(
+                    IteratorUtils.map(
+                            graph.getBaseGraph().findNodes(label.get()).iterator(),
+                            node -> new Neo4jVertex(node, graph)),
+                    vertex -> HasContainer.testAll(vertex, this.hasContainers));
+        } else {
+            // linear scan
+            return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers));
         }
-        return null;
     }
 
-    @Override
+    // TODO: move all this to the traits!
+
     public String toString() {
         if (this.hasContainers.isEmpty())
             return super.toString();
         else
             return 0 == this.ids.length ?
-                    StringFactory.stepString(this, this.hasContainers) :
-                    StringFactory.stepString(this, Arrays.toString(this.ids), this.hasContainers);
+                    StringFactory.stepString(this, this.returnClass.getSimpleName().toLowerCase(), this.hasContainers) :
+                    StringFactory.stepString(this, this.returnClass.getSimpleName().toLowerCase(), Arrays.toString(this.ids), this.hasContainers);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
index 31aa0c5..8a7060c 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
@@ -68,6 +68,7 @@ import java.util.stream.Stream;
 @Graph.OptIn(Graph.OptIn.SUITE_GROOVY_ENVIRONMENT)
 @Graph.OptIn(Graph.OptIn.SUITE_GROOVY_ENVIRONMENT_INTEGRATE)
 @Graph.OptIn(Graph.OptIn.SUITE_GROOVY_ENVIRONMENT_PERFORMANCE)
+@Graph.OptIn("org.apache.tinkerpop.gremlin.neo4j.NativeNeo4jSuite")
 public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
 
     static {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
index 41b6d0f..c59ad3f 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/AbstractNeo4jGraphProvider.java
@@ -75,6 +75,34 @@ public abstract class AbstractNeo4jGraphProvider extends AbstractGraphProvider {
         super.loadGraphData(graph, loadGraphWith, testClass, testName);
     }
 
+    public static void dropIndices(final Neo4jGraph graph, final LoadGraphWith.GraphData graphData) {
+        if (graphData.equals(LoadGraphWith.GraphData.GRATEFUL)) {
+            graph.tx().readWrite();
+            graph.cypher("DROP INDEX ON :artist(name)").iterate();
+            graph.cypher("DROP INDEX ON :song(name)").iterate();
+            graph.cypher("DROP INDEX ON :song(songType)").iterate();
+            graph.cypher("DROP INDEX ON :song(performances)").iterate();
+            graph.tx().commit();
+        } else if (graphData.equals(LoadGraphWith.GraphData.MODERN)) {
+            graph.tx().readWrite();
+            graph.cypher("DROP INDEX ON :person(name)").iterate();
+            graph.cypher("DROP INDEX ON :person(age)").iterate();
+            graph.cypher("DROP INDEX ON :software(name)").iterate();
+            graph.cypher("DROP INDEX ON :software(lang)").iterate();
+            graph.tx().commit();
+        } else if (graphData.equals(LoadGraphWith.GraphData.CLASSIC)) {
+            graph.tx().readWrite();
+            graph.cypher("DROP INDEX ON :vertex(name)").iterate();
+            graph.cypher("DROP INDEX ON :vertex(age)").iterate();
+            graph.cypher("DROP INDEX ON :vertex(lang)").iterate();
+            graph.tx().commit();
+        } else {
+            // TODO: add CREW work here.
+            // TODO: add meta_property indices when meta_property graph is provided
+            //throw new RuntimeException("Could not load graph with " + graphData);
+        }
+    }
+
     private void createIndices(final Neo4jGraph graph, final LoadGraphWith.GraphData graphData) {
         final Random random = new Random();
         final boolean pick = random.nextBoolean();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NativeNeo4jSuite.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NativeNeo4jSuite.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NativeNeo4jSuite.java
index cf23fda..58da3cf 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NativeNeo4jSuite.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/NativeNeo4jSuite.java
@@ -23,6 +23,7 @@ package org.apache.tinkerpop.gremlin.neo4j;
 
 import org.apache.tinkerpop.gremlin.AbstractGremlinSuite;
 import org.apache.tinkerpop.gremlin.neo4j.process.NativeNeo4jCypherTest;
+import org.apache.tinkerpop.gremlin.neo4j.structure.NativeNeo4jIndexTest;
 import org.apache.tinkerpop.gremlin.neo4j.structure.NativeNeo4jStructureTest;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.junit.runners.model.InitializationError;
@@ -37,10 +38,15 @@ public class NativeNeo4jSuite extends AbstractGremlinSuite {
         super(klass, builder,
                 new Class<?>[]{
                         NativeNeo4jStructureTest.class,
+                        NativeNeo4jIndexTest.class,
                         NativeNeo4jCypherTest.class,
                 }, new Class<?>[]{
                         NativeNeo4jStructureTest.class,
-                        NativeNeo4jCypherTest.class}, true, TraversalEngine.Type.STANDARD);
+                        NativeNeo4jIndexTest.class,
+                        NativeNeo4jCypherTest.class
+                },
+                false,
+                TraversalEngine.Type.STANDARD);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexTest.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexTest.java
new file mode 100644
index 0000000..0df3cf2
--- /dev/null
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jIndexTest.java
@@ -0,0 +1,60 @@
+/*
+ *
+ *  * 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.neo4j.structure;
+
+import org.apache.tinkerpop.gremlin.neo4j.AbstractNeo4jGremlinTest;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.util.TimeUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class NativeNeo4jIndexTest extends AbstractNeo4jGremlinTest {
+
+    @Test
+    public void shouldHaveFasterRuntimeWithLabelKeyValueIndex() throws Exception {
+        final Neo4jGraph neo4j = (Neo4jGraph) this.graph;
+        for (int i = 0; i < 10000; i++) {
+            if (i % 2 == 0)
+                this.graph.addVertex(T.label, "something", "myId", i);
+            else
+                this.graph.addVertex(T.label, "nothing", "myId", i);
+        }
+        this.graph.tx().commit();
+        final Runnable traversal = () -> g.V().hasLabel("something").has("myId", 2000).tryNext().get();
+
+        // no index
+        TimeUtil.clock(10, traversal);
+        final double noIndexTime = TimeUtil.clock(20, traversal);
+        // index time
+        neo4j.cypher("CREATE INDEX ON :something(myId)").iterate();
+        this.graph.tx().commit();
+        Thread.sleep(5000); // wait for index to be build just in case
+        TimeUtil.clock(10, traversal);
+        final double indexTime = TimeUtil.clock(20, traversal);
+        //System.out.println(noIndexTime + "----" + indexTime);
+        assertTrue(noIndexTime > indexTime);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/50bd2973/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureTest.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureTest.java
index dc29a91..75e5d80 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureTest.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/structure/NativeNeo4jStructureTest.java
@@ -21,9 +21,7 @@
 
 package org.apache.tinkerpop.gremlin.neo4j.structure;
 
-import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.FeatureRequirement;
-import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
 import org.apache.tinkerpop.gremlin.neo4j.AbstractNeo4jGremlinTest;
 import org.apache.tinkerpop.gremlin.neo4j.structure.trait.MultiMetaNeo4jTrait;