This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch 3.5-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.5-dev by this push:
new cefbecffc3 [TINKERPOP-2973] Enable vertex properties filtering for
GraphComputer (#2164)
cefbecffc3 is described below
commit cefbecffc3f45512a479b642fdee7b8175a2ca11
Author: Boxuan Li <[email protected]>
AuthorDate: Thu Jul 27 16:14:41 2023 -0700
[TINKERPOP-2973] Enable vertex properties filtering for GraphComputer
(#2164)
GraphComputer has vertexFilter and edgeFilter, but not yet a filter for
vertex properties. Many vertex programs don't need many if not all vertex
properties. PageRank, for example, does not need any vertex properties at all.
Having a vertex property filter can greatly reduce memory/disk usage.
Also related to TINKERPOP-1403
---
.../gremlin/process/computer/GraphComputer.java | 11 +++
.../gremlin/process/computer/GraphFilter.java | 99 ++++++++++++++++++----
.../gremlin/structure/util/star/StarGraph.java | 8 ++
.../gremlin/process/TraversalStrategiesTest.java | 6 ++
.../process/computer/GraphComputerTest.java | 29 ++++++-
.../pagerank/PageRankVertexProgramTest.java | 6 +-
.../computer/AbstractHadoopGraphComputer.java | 8 +-
.../gremlin/spark/structure/SparkTest.java | 6 +-
.../process/computer/TinkerGraphComputer.java | 7 ++
.../process/computer/TinkerGraphComputerView.java | 23 ++++-
10 files changed, 176 insertions(+), 27 deletions(-)
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputer.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputer.java
index 5e8fdab5cd..2baba4cb78 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputer.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputer.java
@@ -22,6 +22,7 @@ import
org.apache.tinkerpop.gremlin.process.computer.util.DefaultComputerResult;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import java.util.concurrent.Future;
@@ -135,6 +136,16 @@ public interface GraphComputer {
*/
public GraphComputer edges(final Traversal<Vertex, Edge> edgeFilter)
throws IllegalArgumentException;
+ /**
+ * Add a filter that will limit which vertex properties are loaded from
the graph source. The loaded vertices
+ * will only have those properties that pass through the provided filter.
To drop all vertex properties,
+ * provide a traversal like __.properties("dummy") where "dummy" is not a
valid vertex property.
+ *
+ * @param vertexPropertyFilter the traversal that determines which vertex
properties are loaded for each vertex
+ * @return the updated GraphComputer with newly set vertex property filter
+ */
+ public GraphComputer vertexProperties(final Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter);
+
/**
* Set an arbitrary configuration key/value for the underlying {@code
Configuration} in the {@link GraphComputer}.
* Typically, the other fluent methods in {@link GraphComputer} should be
used to configure the computation.
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java
index 2f01dcf28a..6daa95278b 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java
@@ -27,6 +27,7 @@ import
org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import java.io.Serializable;
@@ -35,6 +36,7 @@ import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -81,6 +83,7 @@ public final class GraphFilter implements Cloneable,
Serializable {
private Traversal.Admin<Vertex, Vertex> vertexFilter = null;
private Traversal.Admin<Vertex, Edge> edgeFilter = null;
+ private Traversal.Admin<Vertex, ? extends Property<?>>
vertexPropertyFilter = null;
private Map<Direction, Map<String, Legal>> edgeLegality = new
EnumMap<>(Direction.class);
private boolean allowNoEdges = false;
@@ -182,6 +185,16 @@ public final class GraphFilter implements Cloneable,
Serializable {
}
}
+ /**
+ * Set the filter for selecting vertex properties from the vertices.
+ *
+ * @param vertexPropertyFilter The {@link Traversal} that will either let
the vertex property pass or not.
+ */
+ public void setVertexPropertyFilter(final Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter) {
+ this.vertexPropertyFilter = vertexPropertyFilter.asAdmin().clone();
+ }
+
+
/**
* Returns true if the provided vertex meets the vertex-filter criteria.
* If no vertex filter is provided, then the vertex is considered legal.
@@ -206,6 +219,19 @@ public final class GraphFilter implements Cloneable,
Serializable {
TraversalUtil.applyAll(vertex, this.edgeFilter);
}
+ /**
+ * Returns an iterator of legal vertex properties. If no vertex property
+ * filter is provided, then all vertex properties are returned.
+ *
+ * @param vertex the vertex whose legal vertex properties are to be
accessed.
+ * @return an iterator of vertex properties that are {@link Legal#YES}.
+ */
+ public Iterator<? extends Property<?>> legalVertexProperties(final Vertex
vertex) {
+ return null == this.vertexPropertyFilter ?
+ vertex.properties() :
+ TraversalUtil.applyAll(vertex, this.vertexPropertyFilter);
+ }
+
/**
* Get the vertex filter associated with this graph filter.
*
@@ -224,13 +250,22 @@ public final class GraphFilter implements Cloneable,
Serializable {
return this.edgeFilter;
}
+ /**
+ * Get the vertex property filter associated with this graph filter.
+ *
+ * @return the vertex property filter or null if not provided.
+ */
+ public Traversal.Admin<Vertex, ? extends Property<?>>
getVertexPropertyFilter() {
+ return this.vertexPropertyFilter;
+ }
+
/**
* Whether filters have been defined.
*
- * @return true if either a vertex or edge filter has been provided.
+ * @return true if either a vertex, edge filter, or vertex property filter
has been provided.
*/
public boolean hasFilter() {
- return this.vertexFilter != null || this.edgeFilter != null;
+ return this.vertexFilter != null || this.edgeFilter != null ||
this.vertexPropertyFilter != null;
}
/**
@@ -251,6 +286,15 @@ public final class GraphFilter implements Cloneable,
Serializable {
return this.vertexFilter != null;
}
+ /**
+ * Whether a vertex property filter has been defined.
+ *
+ * @return true if a vertex property filter was provided.
+ */
+ public boolean hasVertexPropertyFilter() {
+ return this.vertexPropertyFilter != null;
+ }
+
/**
* For a particular edge directionality, get all the {@link Legal#YES} or
{@link Legal#MAYBE} edge labels.
* If the label set contains {@code null}, then all edge labels for that
direction are positively legal.
@@ -312,19 +356,22 @@ public final class GraphFilter implements Cloneable,
Serializable {
@Override
public int hashCode() {
- return (null == this.edgeFilter ? 111 : this.edgeFilter.hashCode()) ^
(null == this.vertexFilter ? 222 : this.vertexFilter.hashCode());
+ int result = vertexFilter != null ? vertexFilter.hashCode() : 0;
+ result = 31 * result + (edgeFilter != null ? edgeFilter.hashCode() :
0);
+ result = 31 * result + (vertexPropertyFilter != null ?
vertexPropertyFilter.hashCode() : 0);
+ return result;
}
@Override
- public boolean equals(final Object object) {
- if (!(object instanceof GraphFilter))
- return false;
- else if (((GraphFilter) object).hasVertexFilter() && !((GraphFilter)
object).vertexFilter.equals(this.vertexFilter))
- return false;
- else if (((GraphFilter) object).hasEdgeFilter() && !((GraphFilter)
object).edgeFilter.equals(this.edgeFilter))
- return false;
- else
- return true;
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ GraphFilter that = (GraphFilter) o;
+
+ if (!Objects.equals(vertexFilter, that.vertexFilter)) return false;
+ if (!Objects.equals(edgeFilter, that.edgeFilter)) return false;
+ return Objects.equals(vertexPropertyFilter, that.vertexPropertyFilter);
}
@Override
@@ -335,6 +382,8 @@ public final class GraphFilter implements Cloneable,
Serializable {
clone.vertexFilter = this.vertexFilter.clone();
if (null != this.edgeFilter)
clone.edgeFilter = this.edgeFilter.clone();
+ if (null != this.vertexPropertyFilter)
+ clone.vertexPropertyFilter = this.vertexPropertyFilter.clone();
return clone;
} catch (final CloneNotSupportedException e) {
throw new IllegalStateException(e.getMessage(), e);
@@ -345,11 +394,25 @@ public final class GraphFilter implements Cloneable,
Serializable {
public String toString() {
if (!this.hasFilter())
return "graphfilter[none]";
- else if (this.hasVertexFilter() && this.hasEdgeFilter())
- return "graphfilter[" + this.vertexFilter + "," + this.edgeFilter
+ "]";
- else if (this.hasVertexFilter())
- return "graphfilter[" + this.vertexFilter + "]";
- else
- return "graphfilter[" + this.edgeFilter + "]";
+ StringBuilder builder = new StringBuilder("graphfilter[");
+ boolean needDelimiter = false;
+ if (this.hasVertexFilter()) {
+ builder.append(this.vertexFilter);
+ needDelimiter = true;
+ }
+ if (this.hasEdgeFilter()) {
+ if (needDelimiter) {
+ builder.append(",");
+ }
+ builder.append(this.edgeFilter);
+ needDelimiter = true;
+ }
+ if (this.hasVertexPropertyFilter()) {
+ if (needDelimiter) {
+ builder.append(",");
+ }
+ builder.append(this.vertexPropertyFilter);
+ }
+ return builder.append("]").toString();
}
}
\ No newline at end of file
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
index 3bcdb7db39..0c47d78caa 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
@@ -47,6 +47,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Stream;
/**
@@ -575,6 +576,13 @@ public final class StarGraph implements Graph,
Serializable {
this.inEdges = inEdges;
}
}
+ if (graphFilter.hasVertexPropertyFilter()) {
+ Set<String> retainSet = new HashSet<>();
+
graphFilter.legalVertexProperties(this).forEachRemaining(property -> {
+ retainSet.add(property.key());
+ });
+ this.vertexProperties.keySet().removeIf(key ->
!retainSet.contains(key));
+ }
return Optional.of(this);
} else {
return Optional.empty();
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
index 1247986361..07abfa8da4 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
@@ -30,6 +30,7 @@ import
org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
import
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.Test;
@@ -168,6 +169,11 @@ public class TraversalStrategiesTest {
return this;
}
+ @Override
+ public GraphComputer vertexProperties(Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter) {
+ return this;
+ }
+
@Override
public Future<ComputerResult> submit() {
return new CompletableFuture<>();
diff --git
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index ce039e8ea0..d489a434d1 100644
---
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -155,6 +155,12 @@ public class GraphComputerTest extends
AbstractGremlinProcessTest {
} catch (final UnsupportedOperationException e) {
assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(),
e.getMessage());
}
+ try {
+ new BadGraphComputer().vertexProperties(__.properties("type"));
+ fail("Should throw an unsupported operation exception");
+ } catch (final UnsupportedOperationException e) {
+
assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(),
e.getMessage());
+ }
} else {
fail("Should not support graph filter: " + BadGraphComputer.class);
}
@@ -197,6 +203,11 @@ public class GraphComputerTest extends
AbstractGremlinProcessTest {
throw GraphComputer.Exceptions.graphFilterNotSupported();
}
+ @Override
+ public GraphComputer vertexProperties(Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter) {
+ throw GraphComputer.Exceptions.graphFilterNotSupported();
+ }
+
@Override
public GraphComputer configure(final String key, final Object value) {
return null;
@@ -1756,13 +1767,19 @@ public class GraphComputerTest extends
AbstractGremlinProcessTest {
} catch (final UnsupportedOperationException e) {
assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(),
e.getMessage());
}
+ try {
+
graphProvider.getGraphComputer(graph).vertexProperties(__.properties("prop1",
"prop2"));
+ fail("Should throw an unsupported operation exception");
+ } catch (final UnsupportedOperationException e) {
+
assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(),
e.getMessage());
+ }
return;
}
/// VERTEX PROGRAM
-
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).program(new
VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).submit().get();
+
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).vertexProperties(__.properties("dummy")).program(new
VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).submit().get();
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).program(new
VertexProgramM(VertexProgramM.PEOPLE_ONLY)).submit().get();
graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).program(new
VertexProgramM(VertexProgramM.KNOWS_ONLY)).submit().get();
-
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).program(new
VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
+
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).vertexProperties(__.properties("name")).edges(__.bothE("knows")).program(new
VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight",
P.gt(0.5f))).program(new
VertexProgramM(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).program(new
VertexProgramM(VertexProgramM.VERTICES_ONLY)).submit().get();
graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).program(new
VertexProgramM(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
@@ -1801,6 +1818,14 @@ public class GraphComputerTest extends
AbstractGremlinProcessTest {
} catch (final IllegalArgumentException e) {
assertEquals(e.getMessage(),
GraphComputer.Exceptions.edgeFilterAccessesAdjacentVertices(__.<Vertex>out().outE()).getMessage());
}
+ try {
+ // VertexProgramM.PEOPLE_KNOWS_ONLY needs name property
+ graphProvider.getGraphComputer(graph)
+
.vertices(__.hasLabel("person")).edges(__.bothE("knows")).vertexProperties(__.properties("dummy"))
+ .program(new
VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
+ } catch (final ExecutionException e) {
+ assertTrue(e.getMessage().contains("The property does not exist as
the key has no associated value for the provided element"));
+ }
}
public static class VertexProgramM implements VertexProgram {
diff --git
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgramTest.java
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgramTest.java
index 6550a325b6..5c6087f9e8 100644
---
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgramTest.java
+++
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgramTest.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith;
import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.junit.Test;
@@ -73,8 +74,9 @@ public class PageRankVertexProgramTest extends
AbstractGremlinProcessTest {
@LoadGraphWith(MODERN)
public void shouldExecutePageRankWithEpsilonBreak() throws Exception {
if
(graphProvider.getGraphComputer(graph).features().supportsResultGraphPersistCombination(GraphComputer.ResultGraph.NEW,
GraphComputer.Persist.VERTEX_PROPERTIES)) {
- final ComputerResult result =
graph.compute(graphProvider.getGraphComputer(graph).getClass()).
-
program(PageRankVertexProgram.build().epsilon(0.00001d).iterations(30).create(graph)).submit().get();
// by using epsilon 0.00001, we should get iterations 11
+ final ComputerResult result =
graph.compute(graphProvider.getGraphComputer(graph).getClass())
+ .vertexProperties(__.properties("name", "age", "lang"))
+
.program(PageRankVertexProgram.build().epsilon(0.00001d).iterations(30).create(graph)).submit().get();
// by using epsilon 0.00001, we should get iterations 11
result.graph().traversal().V().forEachRemaining(v -> {
assertEquals(3, v.keys().size()); // name, age/lang, pageRank
assertTrue(v.keys().contains("name"));
diff --git
a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/AbstractHadoopGraphComputer.java
b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/AbstractHadoopGraphComputer.java
index 278fc507b7..6c37def4d7 100644
---
a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/AbstractHadoopGraphComputer.java
+++
b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/AbstractHadoopGraphComputer.java
@@ -34,8 +34,8 @@ import
org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
import org.apache.tinkerpop.gremlin.process.computer.util.GraphComputerHelper;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.io.Storage;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.Gremlin;
import org.slf4j.Logger;
@@ -88,6 +88,12 @@ public abstract class AbstractHadoopGraphComputer implements
GraphComputer {
return this;
}
+ @Override
+ public GraphComputer vertexProperties(final Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter) {
+ this.graphFilter.setVertexPropertyFilter(vertexPropertyFilter);
+ return this;
+ }
+
@Override
public GraphComputer result(final ResultGraph resultGraph) {
this.resultGraph = resultGraph;
diff --git
a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
index 5aa78a404c..3595800c6a 100644
---
a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
+++
b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/structure/SparkTest.java
@@ -28,6 +28,7 @@ import
org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph;
import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import
org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.spark.AbstractSparkTest;
import org.apache.tinkerpop.gremlin.spark.process.computer.SparkGraphComputer;
import
org.apache.tinkerpop.gremlin.spark.process.computer.SparkHadoopGraphProvider;
@@ -70,7 +71,10 @@ public class SparkTest extends AbstractSparkTest {
assertEquals(i, Spark.getRDDs().size());
configuration.setProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, prefix + i);
Graph graph = GraphFactory.open(configuration);
-
graph.compute(SparkGraphComputer.class).persist(GraphComputer.Persist.VERTEX_PROPERTIES).program(PageRankVertexProgram.build().iterations(1).create(graph)).submit().get();
+ graph.compute(SparkGraphComputer.class)
+ .persist(GraphComputer.Persist.VERTEX_PROPERTIES)
+ .vertexProperties(__.properties("dummy"))
+
.program(PageRankVertexProgram.build().iterations(1).create(graph)).submit().get();
assertNotNull(Spark.getRDD(graphRDDName));
assertEquals(i + 1, Spark.getRDDs().size());
}
diff --git
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputer.java
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputer.java
index bf6f594166..f406847c10 100644
---
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputer.java
+++
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputer.java
@@ -33,6 +33,7 @@ import
org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import
org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
@@ -128,6 +129,12 @@ public final class TinkerGraphComputer implements
GraphComputer {
return this;
}
+ @Override
+ public GraphComputer vertexProperties(Traversal<Vertex, ? extends
Property<?>> vertexPropertyFilter) {
+ this.graphFilter.setVertexPropertyFilter(vertexPropertyFilter);
+ return this;
+ }
+
@Override
public Future<ComputerResult> submit() {
// a graph computer can only be executed once
diff --git
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputerView.java
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputerView.java
index 43998fb292..40a497ba03 100644
---
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputerView.java
+++
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerGraphComputerView.java
@@ -21,6 +21,8 @@ package
org.apache.tinkerpop.gremlin.tinkergraph.process.computer;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -36,9 +38,11 @@ import
org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -55,6 +59,7 @@ public final class TinkerGraphComputerView {
private final Set<Object> legalVertices = new HashSet<>();
private final Map<Object, Set<Object>> legalEdges = new HashMap<>();
private final GraphFilter graphFilter;
+ private final Set<String> retainVertexProperties;
public TinkerGraphComputerView(final TinkerGraph graph, final GraphFilter
graphFilter, final Set<VertexComputeKey> computeKeys) {
this.graph = graph;
@@ -76,6 +81,11 @@ public final class TinkerGraphComputerView {
}
});
}
+ if (this.graphFilter.hasVertexPropertyFilter()) {
+ retainVertexProperties = new
HashSet<>(Arrays.asList(((PropertiesStep)
graphFilter.getVertexPropertyFilter().getStartStep()).getPropertyKeys()));
+ } else {
+ retainVertexProperties = null;
+ }
}
public <V> Property<V> addProperty(final TinkerVertex vertex, final String
key, final V value) {
@@ -97,13 +107,12 @@ public final class TinkerGraphComputerView {
public List<VertexProperty<?>> getProperty(final TinkerVertex vertex,
final String key) {
// if the vertex property is already on the vertex, use that.
final List<VertexProperty<?>> vertexProperty = this.getValue(vertex,
key);
- return vertexProperty.isEmpty() ? (List)
TinkerHelper.getProperties(vertex).getOrDefault(key, Collections.emptyList()) :
vertexProperty;
- //return isComputeKey(key) ? this.getValue(vertex, key) : (List)
TinkerHelper.getProperties(vertex).getOrDefault(key, Collections.emptyList());
+ return vertexProperty.isEmpty() ? (List)
getPropertiesMap(vertex).getOrDefault(key, Collections.emptyList()) :
vertexProperty;
}
public List<Property> getProperties(final TinkerVertex vertex) {
final List<Property> list = new ArrayList<>();
- for (final List<VertexProperty> properties :
TinkerHelper.getProperties(vertex).values()) {
+ for (final List<VertexProperty> properties :
getPropertiesMap(vertex).values()) {
list.addAll(properties);
}
for (final List<VertexProperty<?>> properties :
this.computeProperties.getOrDefault(vertex, Collections.emptyMap()).values()) {
@@ -112,6 +121,14 @@ public final class TinkerGraphComputerView {
return list;
}
+ private Map<String, List<VertexProperty>> getPropertiesMap(final
TinkerVertex vertex) {
+ Map<String, List<VertexProperty>> propertiesMap =
TinkerHelper.getProperties(vertex);
+ if (retainVertexProperties != null) {
+ propertiesMap.keySet().retainAll(retainVertexProperties);
+ }
+ return propertiesMap;
+ }
+
public void removeProperty(final TinkerVertex vertex, final String key,
final VertexProperty property) {
if (isComputeKey(key)) {
this.removeValue(vertex, key, property);