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 2018/12/04 22:00:44 UTC
[tinkerpop] 01/01: TINKERPOP-1849 Provide a way to fold() with an
index
This is an automated email from the ASF dual-hosted git repository.
dkuppitz pushed a commit to branch TINKERPOP-1849
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit e12a9b0d3935606f6eafce90bbb2e5d1e90892eb
Author: Daniel Kuppitz <da...@hotmail.com>
AuthorDate: Tue Dec 4 15:00:15 2018 -0700
TINKERPOP-1849 Provide a way to fold() with an index
---
docs/src/reference/the-traversal.asciidoc | 36 ++++++
.../traversal/dsl/graph/GraphTraversal.java | 23 ++++
.../gremlin/process/traversal/dsl/graph/__.java | 6 +
.../process/traversal/step/map/IndexStep.java | 118 +++++++++++++++++++
.../process/traversal/step/util/WithOptions.java | 19 +++
.../process/traversal/step/map/IndexStepTest.java | 49 ++++++++
.../Process/Traversal/GraphTraversal.cs | 9 ++
.../Gremlin.Net/Process/Traversal/WithOptions.cs | 9 ++
.../src/Gremlin.Net/Process/Traversal/__.cs | 8 ++
.../lib/process/graph-traversal.js | 11 ++
.../gremlin-javascript/lib/process/traversal.js | 5 +-
.../gremlin_python/process/graph_traversal.py | 12 ++
.../jython/gremlin_python/process/traversal.py | 6 +
gremlin-test/features/map/Index.feature | 65 +++++++++++
.../gremlin/process/ProcessStandardSuite.java | 4 +
.../process/traversal/step/map/IndexTest.java | 129 +++++++++++++++++++++
.../tinkergraph/structure/TinkerGraphPlayTest.java | 32 +----
17 files changed, 514 insertions(+), 27 deletions(-)
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 1e43e9f..1f2cc24 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1084,6 +1084,42 @@ g.V().identity()
link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#identity--++[`identity()`]
+[[index-step]]
+=== Index Step
+
+The `index()`-step (*map*) indexes each element in the current collection. If the current traverser's value is not a collection, then it's treated as a single-item collection. There two indexers
+available, which can be chosen using the `with()` modulator. The list indexer (default) creates a list for each collection item, with the first item being the original element and the second element
+being the index. The map indexer created a linked hash map in which the index represents the key and the original item is used as the value.
+
+[gremlin.groovy,modern]
+----
+g.V().hasLabel("software").values("name").fold().
+ order(Scope.local).
+ index().
+ unfold().
+ order().
+ by(__.tail(Scope.local, 1)) <1>
+g.V().hasLabel("software").values("name").fold().
+ order(Scope.local).
+ index().
+ with(WithOptions.indexer, WithOptions.list).
+ unfold().
+ order().
+ by(__.tail(Scope.local, 1)) <2>
+g.V().hasLabel("person").values("name").fold().
+ order(Scope.local).
+ index().
+ with(WithOptions.indexer, WithOptions.map)
+----
+
+<1> Index all software names in their alphabetical order.
+<2> Same as statement 1, but with an explicitely specified list indexer.
+<3> Index all person names in their alphabetical order and store the result in an ordered map.
+
+*Additional References*
+
+link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#index--++[`index()`]
+
[[inject-step]]
=== Inject Step
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 1ef0be7..372710d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -85,6 +85,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IndexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaCollectingBarrierStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
@@ -2561,6 +2562,27 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
+ * Indexes all items of the current collection. The indexing format can be configured using the {@link GraphTraversal#with(String, Object)}
+ * and {@link org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions#indexer}.
+ *
+ * Indexed as list: ["a","b","c"] => [["a",0],["b",1],["c",2]]
+ * Indexed as map: ["a","b","c"] => {0:"a",1:"b",2:"c"}
+ *
+ * If the current object is not a collection, this step will map the object to a single item collection/map:
+ *
+ * Indexed as list: "a" => ["a",0]
+ * Indexed as map: "a" => {0:"a"}
+ *
+ * @return the traversal with an appended {@link IndexStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#index-step" target="_blank">Reference Documentation - Index Step</a>
+ * @since 3.4.0
+ */
+ public default <E2> GraphTraversal<S, E2> index() {
+ this.asAdmin().getBytecode().addStep(Symbols.index);
+ return this.asAdmin().addStep(new IndexStep<>(this.asAdmin()));
+ }
+
+ /**
* Turns the lazy traversal pipeline into a bulk-synchronous pipeline which basically iterates that traversal to
* the size of the barrier. In this case, it iterates the entire thing as the default barrier size is set to
* {@code Integer.MAX_VALUE}.
@@ -2934,6 +2956,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public static final String aggregate = "aggregate";
public static final String subgraph = "subgraph";
public static final String barrier = "barrier";
+ public static final String index = "index";
public static final String local = "local";
public static final String emit = "emit";
public static final String repeat = "repeat";
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index c0f9cad..f991e80 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -1125,4 +1125,10 @@ public class __ {
return __.<A>start().barrier(barrierConsumer);
}
+ /**
+ * @see GraphTraversal#index()
+ */
+ public static <A, B> GraphTraversal<A, B> index() {
+ return __.<A>start().index();
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java
new file mode 100644
index 0000000..b903c15
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStep.java
@@ -0,0 +1,118 @@
+/*
+ * 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.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class IndexStep<S, E> extends MapStep<S, E> implements TraversalParent, Configuring {
+
+ private final static IllegalArgumentException INVALID_CONFIGURATION_EXCEPTION =
+ new IllegalArgumentException("WithOptions.indexer requires a single Integer argument (possible " + "" +
+ "values are: WithOptions.[list|map])");
+
+ private final Parameters parameters = new Parameters();
+
+ private Function<Iterator, Object> indexer;
+
+ public IndexStep(final Traversal.Admin traversal) {
+ super(traversal);
+ this.configure(WithOptions.indexer, WithOptions.list);
+ }
+
+ @Override
+ protected E map(final Traverser.Admin<S> traverser) {
+ //noinspection unchecked
+ return (E) indexer.apply(IteratorUtils.asIterator(traverser.get()));
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ this.indexer.hashCode();
+ }
+
+ private static List<List<Object>> indexedList(final Iterator iterator) {
+ final List<List<Object>> list = new ArrayList<>();
+ int i = 0;
+ while (iterator.hasNext()) {
+ list.add(Arrays.asList(iterator.next(), i++));
+ }
+ return Collections.unmodifiableList(list);
+ }
+
+ private static Map<Integer, Object> indexedMap(final Iterator iterator) {
+ final Map<Integer, Object> map = new LinkedHashMap<>();
+ int i = 0;
+ while (iterator.hasNext()) {
+ map.put(i++, iterator.next());
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+
+ @Override
+ public void configure(final Object... keyValues) {
+ final Integer indexer;
+ if (keyValues[0].equals(WithOptions.indexer)) {
+ if (keyValues.length == 2 && keyValues[1] instanceof Integer) {
+ indexer = (Integer) keyValues[1];
+ } else {
+ throw INVALID_CONFIGURATION_EXCEPTION;
+ }
+ if (indexer == WithOptions.list) {
+ this.indexer = IndexStep::indexedList;
+ } else if (indexer == WithOptions.map) {
+ this.indexer = IndexStep::indexedMap;
+ } else {
+ throw INVALID_CONFIGURATION_EXCEPTION;
+ }
+ } else {
+ this.parameters.set(this, keyValues);
+ }
+ }
+
+ @Override
+ public Parameters getParameters() {
+ return parameters;
+ }
+}
+
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
index 3faa95d..e8e695f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
@@ -67,4 +67,23 @@ public class WithOptions {
* Include all tokens.
*/
public static int all = ids | labels | keys | values;
+
+ //
+ // IndexStep
+ //
+
+ /**
+ * Configures the indexer to be used in {@link org.apache.tinkerpop.gremlin.process.traversal.step.map.IndexStep}.
+ */
+ public static final String indexer = Graph.Hidden.hide("tinkerpop.index.indexer");
+
+ /**
+ * Index items using 2-item lists.
+ */
+ public static int list = 0;
+
+ /**
+ * Index items using a {@link java.util.LinkedHashMap}.
+ */
+ public static int map = 1;
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStepTest.java
new file mode 100644
index 0000000..a3b4071
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexStepTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class IndexStepTest extends StepTest {
+
+ @Override
+ protected List<Traversal> getTraversals() {
+ return Arrays.asList(
+ __.index(),
+ __.index().with(WithOptions.indexer, WithOptions.map)
+ );
+ }
+
+ @Test
+ public void testDefault() {
+ assertEquals(__.index(), __.index().with(WithOptions.indexer, WithOptions.list));
+ }
+}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 5437c39..e1cfd64 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -841,6 +841,15 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
+ /// Adds the index step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public GraphTraversal<S, E2> Index<E2> ()
+ {
+ Bytecode.AddStep("index");
+ return Wrap<S, E2>(this);
+ }
+
+ /// <summary>
/// Adds the inject step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
public GraphTraversal<S, E> Inject (params E[] injections)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
index 8b79089..c20c59a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
@@ -59,6 +59,15 @@ namespace Gremlin.Net.Process.Traversal.Step.Util
public static readonly int All = 15;
+
+ public static readonly string Indexer = "~tinkerpop.index.indexer";
+
+
+ public static readonly int List = 0;
+
+
+ public static readonly int Map = 1;
+
}
#pragma warning restore 1591
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 3681ce6..daea514 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -623,6 +623,14 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the index step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, E2> Index<E2>()
+ {
+ return new GraphTraversal<object, E2>().Index<E2>();
+ }
+
+ /// <summary>
/// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the inject step to that traversal.
/// </summary>
public static GraphTraversal<object, object> Inject(params object[] injections)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index bcb37fa..ec554e6 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -603,6 +603,16 @@ class GraphTraversal extends Traversal {
}
/**
+ * Graph traversal index method.
+ * @param {...Object} args
+ * @returns {GraphTraversal}
+ */
+ index(...args) {
+ this.bytecode.addStep('index', args);
+ return this;
+ }
+
+ /**
* Graph traversal inject method.
* @param {...Object} args
* @returns {GraphTraversal}
@@ -1251,6 +1261,7 @@ const statics = {
in_: (...args) => callOnEmptyTraversal('in_', args),
inE: (...args) => callOnEmptyTraversal('inE', args),
inV: (...args) => callOnEmptyTraversal('inV', args),
+ index: (...args) => callOnEmptyTraversal('index', args),
inject: (...args) => callOnEmptyTraversal('inject', args),
is: (...args) => callOnEmptyTraversal('is', args),
key: (...args) => callOnEmptyTraversal('key', args),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 4517689..2173ade 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -396,7 +396,10 @@ const withOptions = {
labels: 2,
keys: 4,
values: 8,
- all: 15
+ all: 15,
+ indexer: "~tinkerpop.index.indexer",
+ list: 0,
+ map: 1
};
function toEnum(typeName, keys) {
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index 7d7a4c9..b71c9e1 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -295,6 +295,10 @@ class GraphTraversal(Traversal):
self.bytecode.add_step("in", *args)
return self
+ def index(self, *args):
+ self.bytecode.add_step("index", *args)
+ return self
+
def inject(self, *args):
self.bytecode.add_step("inject", *args)
return self
@@ -695,6 +699,10 @@ class __(object):
return cls.graph_traversal(None, None, Bytecode()).in_(*args)
@classmethod
+ def index(cls, *args):
+ return cls.graph_traversal(None, None, Bytecode()).index(*args)
+
+ @classmethod
def inject(cls, *args):
return cls.graph_traversal(None, None, Bytecode()).inject(*args)
@@ -1048,6 +1056,10 @@ def in_(*args):
return __.in_(*args)
statics.add_static('in_', in_)
+def index(*args):
+ return __.index(*args)
+statics.add_static('index', index)
+
def inject(*args):
return __.inject(*args)
statics.add_static('inject', inject)
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index e92d0cb..0825fb9 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -637,3 +637,9 @@ class WithOptions(object):
all = 15
+ indexer = "~tinkerpop.index.indexer"
+
+ list = 0
+
+ map = 1
+
diff --git a/gremlin-test/features/map/Index.feature b/gremlin-test/features/map/Index.feature
new file mode 100644
index 0000000..04c190b
--- /dev/null
+++ b/gremlin-test/features/map/Index.feature
@@ -0,0 +1,65 @@
+# 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.
+
+Feature: Step - index()
+
+ Scenario: g_V_hasLabelXsoftwareX_index_unfold
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("software").index().unfold()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[v[lop],d[0].i] |
+ | l[v[ripple],d[0].i] |
+
+ Scenario: g_V_hasLabelXsoftwareX_order_byXnameX_index_withXmapX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("software").order().by("name").index().with(WithOptions.indexer, WithOptions.map)
+ """
+ When iterated to list
+ Then the result should be ordered
+ | result |
+ | m[{"d[0].i": "v[lop]"}] |
+ | m[{"d[0].i": "v[ripple]"}] |
+
+ Scenario: g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("software").values("name").fold().order(Scope.local).index().unfold().order().by(__.tail(Scope.local, 1))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[lop,d[0].i] |
+ | l[ripple,d[1].i] |
+
+ Scenario: g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("person").values("name").fold().order(Scope.local).index().with(WithOptions.indexer, WithOptions.map)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"d[0].i": "josh", "d[1].i": "marko", "d[2].i": "peter", "d[3].i": "vadas"}] |
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index f3eb669..3ca0644 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -51,6 +51,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IndexTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LoopsTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest;
@@ -141,7 +142,9 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
FlatMapTest.Traversals.class,
FoldTest.Traversals.class,
GraphTest.Traversals.class,
+ IndexTest.Traversals.class,
LoopsTest.Traversals.class,
+ IndexTest.Traversals.class,
MapTest.Traversals.class,
MatchTest.CountMatchTraversals.class,
MatchTest.GreedyMatchTraversals.class,
@@ -231,6 +234,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
FlatMapTest.class,
FoldTest.class,
LoopsTest.class,
+ IndexTest.class,
MapTest.class,
MatchTest.class,
MathTest.class,
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexTest.java
new file mode 100644
index 0000000..36ef074
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IndexTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.step.map;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.tail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+@RunWith(GremlinProcessRunner.class)
+public abstract class IndexTest extends AbstractGremlinProcessTest {
+
+ public abstract Traversal<Vertex, List<Object>> get_g_V_hasLabelXsoftwareX_index_unfold();
+
+ public abstract Traversal<Vertex, Map<Integer, Vertex>> get_g_V_hasLabelXsoftwareX_order_byXnameX_index_withXmapX();
+
+ public abstract Traversal<Vertex, List<Object>> get_g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX();
+
+ public abstract Traversal<Vertex, Map<Integer, String>> get_g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX();
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_hasLabelXsoftwareX_index() {
+ final Traversal<Vertex, List<Object>> traversal = get_g_V_hasLabelXsoftwareX_index_unfold();
+ printTraversalForm(traversal);
+ checkResults(Arrays.asList(
+ Arrays.asList(convertToVertex("lop"), 0),
+ Arrays.asList(convertToVertex("ripple"), 0)
+ ), traversal);
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_hasLabelXsoftwareX_order_byXnameX_index_withXmapX() {
+ final Traversal<Vertex, Map<Integer, Vertex>> traversal = get_g_V_hasLabelXsoftwareX_order_byXnameX_index_withXmapX();
+ printTraversalForm(traversal);
+ final Map<Integer, Vertex> map1 = new LinkedHashMap<>();
+ final Map<Integer, Vertex> map2 = new LinkedHashMap<>();
+ map1.put(0, convertToVertex("lop"));
+ map2.put(0, convertToVertex("ripple"));
+ checkOrderedResults(Arrays.asList(map1, map2), traversal);
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX() {
+ final Traversal<Vertex, List<Object>> traversal = get_g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX();
+ printTraversalForm(traversal);
+ checkOrderedResults(Arrays.asList(
+ Arrays.asList("lop", 0),
+ Arrays.asList("ripple", 1)), traversal);
+ assertFalse(traversal.hasNext());
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX() {
+ final Traversal<Vertex, Map<Integer, String>> traversal = get_g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX();
+ printTraversalForm(traversal);
+ final Map<Integer, String> expected = new LinkedHashMap<>();
+ expected.put(0, "josh");
+ expected.put(1, "marko");
+ expected.put(2, "peter");
+ expected.put(3, "vadas");
+ assertEquals(expected, traversal.next());
+ assertFalse(traversal.hasNext());
+ }
+
+ public static class Traversals extends IndexTest {
+
+ @Override
+ public Traversal<Vertex, List<Object>> get_g_V_hasLabelXsoftwareX_index_unfold() {
+ return g.V().hasLabel("software").index().unfold();
+ }
+
+ @Override
+ public Traversal<Vertex, Map<Integer, Vertex>> get_g_V_hasLabelXsoftwareX_order_byXnameX_index_withXmapX() {
+ return g.V().hasLabel("software").order().by("name")
+ .<Map<Integer, Vertex>> index().with(WithOptions.indexer, WithOptions.map);
+ }
+
+ @Override
+ public Traversal<Vertex, List<Object>> get_g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX() {
+ return g.V().hasLabel("software").values("name").fold().order(Scope.local).index()
+ .<List<Object>> unfold().order().by(tail(Scope.local, 1));
+ }
+
+ @Override
+ public Traversal<Vertex, Map<Integer, String>> get_g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX() {
+ return g.V().hasLabel("person").values("name").fold().order(Scope.local)
+ .<Map<Integer, String>> index().with(WithOptions.indexer, WithOptions.map);
+ }
+ }
+}
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index a2019ae..c453a38 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
import org.apache.tinkerpop.gremlin.structure.*;
@@ -118,33 +119,12 @@ public class TinkerGraphPlayTest {
@Test
@Ignore
public void testPlayDK() throws Exception {
- TinkerGraph graph = TinkerFactory.createTheCrew();
- GraphTraversalSource g = graph.traversal().withStrategies(
- SubgraphStrategy.build().vertexProperties(hasNot("endTime")).create());
-
- System.out.println("\n--- valueMap().by(unfold()) ---");
- g.V().valueMap().forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()) ---");
- g.V().valueMap().by(unfold()).forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()).with(tokens) ---");
- g.V().valueMap().by(unfold()).with(tokens).forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()).with(tokens, false) ---");
- g.V().valueMap().by(unfold()).with(tokens, false).forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids) ---");
- g.V().valueMap().by(unfold()).with(tokens, ids).forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()).with(tokens, labels) ---");
- g.V().valueMap().by(unfold()).with(tokens, labels).forEachRemaining(System.out::println);
-
- System.out.println("\n--- valueMap().by(unfold()).with(tokens, all) ---");
- g.V().valueMap().by(unfold()).with(tokens, all).forEachRemaining(System.out::println);
+ GraphTraversalSource g = TinkerFactory.createModern().traversal();
- System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids | labels) ---");
- g.V().valueMap().by(unfold()).with(tokens, ids | labels).forEachRemaining(System.out::println);
+ g.V().index().forEachRemaining(System.out::println);
+ g.V().fold().index().forEachRemaining(System.out::println);
+ g.V().index().with(WithOptions.indexer, WithOptions.list).forEachRemaining(System.out::println);
+ g.V().fold().index().with(WithOptions.indexer, WithOptions.map).forEachRemaining(System.out::println);
}
@Test