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/01 17:33:36 UTC
incubator-tinkerpop git commit: fixed a Vertex.remove() bug that
showed up in VertexTest for Neo4jGraph. Neo4jGraphStep now relies on the
Neo4jTrait for index lookups. Added a WARNING to docs about Neo4j and multi-
meta- properties.
Repository: incubator-tinkerpop
Updated Branches:
refs/heads/master c520013de -> 8250a2f91
fixed a Vertex.remove() bug that showed up in VertexTest for Neo4jGraph. Neo4jGraphStep now relies on the Neo4jTrait for index lookups. Added a WARNING to docs about Neo4j and multi- meta- properties.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/8250a2f9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/8250a2f9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/8250a2f9
Branch: refs/heads/master
Commit: 8250a2f9155b20c8132770eef40867ca9722dd47
Parents: c520013
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Jun 1 09:33:38 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Jun 1 09:33:38 2015 -0600
----------------------------------------------------------------------
docs/src/implementations.asciidoc | 6 +-
.../step/sideEffect/Neo4jGraphStep.java | 52 +--------------
.../gremlin/neo4j/structure/Neo4jGraph.java | 22 ++++---
.../structure/trait/MultiMetaNeo4jTrait.java | 24 +++++--
.../neo4j/structure/trait/Neo4jTrait.java | 8 +++
.../trait/NoMultiNoMetaNeo4jTrait.java | 68 ++++++++++++++++++++
6 files changed, 114 insertions(+), 66 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/docs/src/implementations.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/implementations.asciidoc b/docs/src/implementations.asciidoc
index 3bad2a9..d759742 100644
--- a/docs/src/implementations.asciidoc
+++ b/docs/src/implementations.asciidoc
@@ -556,9 +556,11 @@ gremlin> graph = Neo4jGraph.open('/tmp/neo4j')
For those leveraging Neo4j High Availability, configure `Neo4jGraph` for "HA mode" by setting the `gremlin.neo4j.ha` flag to `true` in the `Configuration` object passed to `Neo4jGraph.open()`. Note that when the flag is set (by default it is `false`), the `Neo4jGraph` instance expects HA configuration settings to be present. As with embedded Neo4j, HA configuration keys should be prefixed with `gremlin.neo4j.conf`. Please consult Neo4j documentation for more information on link:http://docs.neo4j.org/chunked/stable/ha.html[High Availability] configuration.
-IMPORTANT: `Neo4jGraph` supports both meta- and multi-properties (see <<_vertex_properties,vertex properties>>). However, these are implemented by making use of "hidden" Neo4j nodes. For example, when a vertex has multiple "name" properties, each property is a new node (multi-properties) which can have properties attached to it (meta-properties). As such, the underlying representation may become difficult to query directly using another graph language such as Cypher. The default setting is to disable multi- and meta-properties. However, if this feature is desired, then it can be activated via `gremlin.neo4j.metaProperties` and `gremlin.neo4j.multiProperties` configurations being set to `true`. Once the configuration is set, it can not be changed for the lifetime of the graph.
+IMPORTANT: `Neo4jGraph` supports both multi- and meta-properties (see <<_vertex_properties,vertex properties>>). This is not a native feature of Neo4j and is implemented by making use of "hidden" Neo4j nodes. For example, when a vertex has multiple "name" properties, each property is a new node (multi-properties) which can have properties attached to it (meta-properties). As such, the native, underlying representation may become difficult to query directly using another graph language such as Cypher. The default setting is to disable multi- and meta-properties. However, if this feature is desired, then it can be activated via `gremlin.neo4j.metaProperties` and `gremlin.neo4j.multiProperties` configurations being set to `true`. Once the configuration is set, it can not be changed for the lifetime of the graph.
-TIP: To host Neo4j in Gremlin Server, the dependencies must first be "installed" or otherwise copied to the Gremlin Server path. The automated method for doing this would be to execute `bin/gremlin-server.sh -i org.apache.tinkerpop neo4j-gremlin x.y.z`.
+WARNING: `Neo4jGraph` without multi- and meta-properties is in 1-to-1 correspondence with the native, underlying Neo4j representation. It is recommended that if the user does not require these features, then they should not enable them. Without multi- and meta-properties enabled, Neo4j can be interacted with with other tools and technologies that do not leverage TinkerPop.
+
+TIP: To host Neo4j in Gremlin Server, the dependencies must first be "installed" or otherwise copied to the Gremlin Server path. The automated method for doing this would be to execute `bin/gremlin-server.sh -i org.apache.tinkerpop neo4j-gremlin x.y.z`.
Indices
~~~~~~~
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/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 f274e32..4d25c13 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
@@ -19,13 +19,10 @@
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.process.traversal.Compare;
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.StringFactory;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -34,7 +31,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
-import java.util.Optional;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -59,55 +55,9 @@ public final class Neo4jGraphStep<S extends Element> extends GraphStep<S> {
private Iterator<? extends Vertex> vertices() {
final Neo4jGraph graph = (Neo4jGraph) this.getTraversal().getGraph().get();
- // ids are present, filter on them first
- if (this.ids != null && this.ids.length > 0)
- return IteratorUtils.filter(graph.vertices(this.ids), vertex -> HasContainer.testAll((Vertex) vertex, this.hasContainers));
- ////// do index lookups //////
- graph.tx().readWrite();
- // 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));
- }
- }
- }
- 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 graph.getTrait().lookupVertices(graph, this.hasContainers, this.ids);
}
- // TODO: move all this to the traits!
-
public String toString() {
if (this.hasContainers.isEmpty())
return super.toString();
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/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 8a7060c..c4dac93 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
@@ -109,7 +109,7 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
this.neo4jGraphVariables.set(Graph.Hidden.hide(CONFIG_MULTI_PROPERTIES), supportsMultiProperties);
if (!hasMetaProperties.isPresent())
this.neo4jGraphVariables.set(Graph.Hidden.hide(CONFIG_META_PROPERTIES), supportsMetaProperties);
- this.trait = supportsMultiProperties ? new MultiMetaNeo4jTrait() : new NoMultiNoMetaNeo4jTrait();
+ this.trait = supportsMultiProperties ? MultiMetaNeo4jTrait.instance() : NoMultiNoMetaNeo4jTrait.instance();
this.tx().commit();
}
@@ -168,14 +168,14 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
@Override
public Iterator<Vertex> vertices(final Object... vertexIds) {
this.tx().readWrite();
+ final Predicate<Neo4jNode> nodePredicate = this.trait.getNodePredicate();
if (0 == vertexIds.length) {
- final Predicate<Neo4jNode> nodePredicate = this.trait.getNodePredicate();
return IteratorUtils.stream(this.getBaseGraph().allNodes())
.filter(nodePredicate)
.map(node -> (Vertex) new Neo4jVertex(node, this)).iterator();
} else {
ElementHelper.validateMixedElementIds(Vertex.class, vertexIds);
- return Stream.of(vertexIds)
+ return (Iterator) Stream.of(vertexIds)
.map(id -> {
if (id instanceof Number)
return ((Number) id).longValue();
@@ -188,26 +188,28 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
})
.flatMap(id -> {
try {
- return Stream.of((Vertex) new Neo4jVertex(this.baseGraph.getNodeById(id), this));
+ return Stream.of(this.baseGraph.getNodeById(id));
} catch (final RuntimeException e) {
if (Neo4jHelper.isNotFound(e)) return Stream.empty();
throw e;
}
- }).iterator();
+ })
+ .filter(nodePredicate)
+ .map(node -> new Neo4jVertex(node, this)).iterator();
}
}
@Override
public Iterator<Edge> edges(final Object... edgeIds) {
this.tx().readWrite();
+ final Predicate<Neo4jRelationship> relationshipPredicate = this.trait.getRelationshipPredicate();
if (0 == edgeIds.length) {
- final Predicate<Neo4jRelationship> relationshipPredicate = this.trait.getRelationshipPredicate();
return IteratorUtils.stream(this.getBaseGraph().allRelationships())
.filter(relationshipPredicate)
.map(relationship -> (Edge) new Neo4jEdge(relationship, this)).iterator();
} else {
ElementHelper.validateMixedElementIds(Edge.class, edgeIds);
- return Stream.of(edgeIds)
+ return (Iterator) Stream.of(edgeIds)
.map(id -> {
if (id instanceof Number)
return ((Number) id).longValue();
@@ -220,12 +222,14 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
})
.flatMap(id -> {
try {
- return Stream.of((Edge) new Neo4jEdge(this.baseGraph.getRelationshipById(id), this));
+ return Stream.of(this.baseGraph.getRelationshipById(id));
} catch (final RuntimeException e) {
if (Neo4jHelper.isNotFound(e)) return Stream.empty();
throw e;
}
- }).iterator();
+ })
+ .filter(relationshipPredicate)
+ .map(relationship -> new Neo4jEdge(relationship, this)).iterator();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
index 336858c..bd6142d 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/MultiMetaNeo4jTrait.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jHelper;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jProperty;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Property;
@@ -42,6 +43,7 @@ import org.neo4j.tinkerpop.api.Neo4jRelationship;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -51,6 +53,8 @@ import java.util.stream.Stream;
*/
public class MultiMetaNeo4jTrait implements Neo4jTrait {
+ private static final MultiMetaNeo4jTrait INSTANCE = new MultiMetaNeo4jTrait();
+
public static final String VERTEX_PROPERTY_LABEL = "vertexProperty";
public static final String VERTEX_PROPERTY_PREFIX = Graph.Hidden.hide("");
public static final String VERTEX_PROPERTY_TOKEN = Graph.Hidden.hide("vertexProperty");
@@ -58,6 +62,14 @@ public class MultiMetaNeo4jTrait implements Neo4jTrait {
private static final Predicate<Neo4jNode> NODE_PREDICATE = node -> !node.hasLabel(VERTEX_PROPERTY_LABEL);
private static final Predicate<Neo4jRelationship> RELATIONSHIP_PREDICATE = relationship -> !relationship.type().startsWith(VERTEX_PROPERTY_PREFIX);
+ private MultiMetaNeo4jTrait() {
+
+ }
+
+ public static MultiMetaNeo4jTrait instance() {
+ return INSTANCE;
+ }
+
@Override
public Predicate<Neo4jNode> getNodePredicate() {
return NODE_PREDICATE;
@@ -72,13 +84,12 @@ public class MultiMetaNeo4jTrait implements Neo4jTrait {
public void removeVertex(final Neo4jVertex vertex) {
try {
final Neo4jNode node = vertex.getBaseVertex();
- for (final Neo4jRelationship relationship : node.relationships(Neo4jDirection.OUTGOING)) {
+ for (final Neo4jRelationship relationship : node.relationships(Neo4jDirection.BOTH)) {
final Neo4jNode otherNode = relationship.other(node);
if (otherNode.hasLabel(VERTEX_PROPERTY_LABEL)) {
- otherNode.relationships(Neo4jDirection.BOTH).forEach(Neo4jRelationship::delete);
otherNode.delete(); // meta property node
- } else
- relationship.delete();
+ }
+ relationship.delete();
}
node.delete();
} catch (final IllegalStateException ignored) {
@@ -247,6 +258,11 @@ public class MultiMetaNeo4jTrait implements Neo4jTrait {
key -> (Property<V>) new Neo4jProperty<>(vertexProperty, key, (V) vertexPropertyNode.getProperty(key)));
}
+ @Override
+ public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids) {
+ return NoMultiNoMetaNeo4jTrait.instance().lookupVertices(graph, hasContainers, ids);
+ }
+
/*
@Override
public Set<String> keys() {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
index 9bb79ec..acfa0c6 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/Neo4jTrait.java
@@ -21,14 +21,18 @@
package org.apache.tinkerpop.gremlin.neo4j.structure.trait;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.neo4j.tinkerpop.api.Neo4jNode;
import org.neo4j.tinkerpop.api.Neo4jRelationship;
import java.util.Iterator;
+import java.util.List;
import java.util.function.Predicate;
/**
@@ -64,4 +68,8 @@ public interface Neo4jTrait {
public <V> Iterator<Property<V>> getProperties(final Neo4jVertexProperty vertexProperty, final String... keys);
+ ////
+
+ public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids);
+
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8250a2f9/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
index d1647ad..8961dba 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/trait/NoMultiNoMetaNeo4jTrait.java
@@ -21,10 +21,15 @@
package org.apache.tinkerpop.gremlin.neo4j.structure.trait;
+import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jHelper;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex;
import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty;
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -33,6 +38,8 @@ import org.neo4j.tinkerpop.api.Neo4jNode;
import org.neo4j.tinkerpop.api.Neo4jRelationship;
import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
import java.util.function.Predicate;
/**
@@ -40,8 +47,18 @@ import java.util.function.Predicate;
*/
public class NoMultiNoMetaNeo4jTrait implements Neo4jTrait {
+ private static final NoMultiNoMetaNeo4jTrait INSTANCE = new NoMultiNoMetaNeo4jTrait();
+
private final static Predicate TRUE_PREDICATE = x -> true;
+ public static NoMultiNoMetaNeo4jTrait instance() {
+ return INSTANCE;
+ }
+
+ private NoMultiNoMetaNeo4jTrait() {
+
+ }
+
@Override
public Predicate<Neo4jNode> getNodePredicate() {
return TRUE_PREDICATE;
@@ -130,4 +147,55 @@ public class NoMultiNoMetaNeo4jTrait implements Neo4jTrait {
public <V> Iterator<Property<V>> getProperties(final Neo4jVertexProperty vertexProperty, final String... keys) {
throw VertexProperty.Exceptions.metaPropertiesNotSupported();
}
+
+ @Override
+ public Iterator<Vertex> lookupVertices(final Neo4jGraph graph, final List<HasContainer> hasContainers, final Object... ids) {
+ // ids are present, filter on them first
+ if (ids.length > 0)
+ return IteratorUtils.filter(graph.vertices(ids), vertex -> HasContainer.testAll(vertex, hasContainers));
+ ////// do index lookups //////
+ graph.tx().readWrite();
+ // get a label being search on
+ final Optional<String> label = 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 : hasContainers) {
+ if (hasContainer.getPredicate().equals(Compare.eq)) {
+ if (graph.getBaseGraph().hasSchemaIndex(label.get(), hasContainer.getKey())) {
+ return IteratorUtils.filter(
+ IteratorUtils.map(
+ IteratorUtils.filter(graph.getBaseGraph().findNodes(label.get(), hasContainer.getKey(), hasContainer.getValue()).iterator(), getNodePredicate()),
+ node -> new Neo4jVertex(node, graph)),
+ vertex -> HasContainer.testAll(vertex, hasContainers));
+ }
+ }
+ }
+ } else {
+ // find a vertex by key/value
+ for (final HasContainer hasContainer : hasContainers) {
+ if (hasContainer.getPredicate().equals(Compare.eq)) {
+ return IteratorUtils.filter(
+ IteratorUtils.map(
+ IteratorUtils.filter(graph.getBaseGraph().findNodes(hasContainer.getKey(), hasContainer.getValue()).iterator(), getNodePredicate()),
+ node -> new Neo4jVertex(node, graph)),
+ vertex -> HasContainer.testAll(vertex, hasContainers));
+ }
+ }
+ }
+ if (label.isPresent()) {
+ // find a vertex by label
+ return IteratorUtils.filter(
+ IteratorUtils.map(
+ IteratorUtils.filter(graph.getBaseGraph().findNodes(label.get()).iterator(), getNodePredicate()),
+ node -> new Neo4jVertex(node, graph)),
+ vertex -> HasContainer.testAll(vertex, hasContainers));
+ } else {
+ // linear scan
+ return IteratorUtils.filter(graph.vertices(), vertex -> HasContainer.testAll(vertex, hasContainers));
+ }
+ }
}