You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2022/06/29 20:00:08 UTC

[tinkerpop] branch master updated: TINKERPOP-2742: Warn users of vertex property cardinality mismatch

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new 68d15dde6f TINKERPOP-2742: Warn users of vertex property cardinality mismatch
     new 08faf9221d Merge pull request #1719 from li-boxuan/warn-cardinality-in-io-step
68d15dde6f is described below

commit 68d15dde6fe9ce0facc1adbfaee2e3da11bad214
Author: Boxuan Li <li...@connect.hku.hk>
AuthorDate: Sat Jun 18 11:11:00 2022 -0400

    TINKERPOP-2742: Warn users of vertex property cardinality mismatch
---
 docs/src/reference/the-traversal.asciidoc          |  4 +++
 .../gremlin/structure/util/Attachable.java         | 29 +++++++++++++++++-----
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index e2613238a1..a9244695b2 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1622,6 +1622,10 @@ time is not critical) that are loading to an empty graph - incremental loading i
 writing perspective is not that different in there are no parallel operations in play, however streaming the output
 to disk requires a single pass of the data without high memory requirements for larger datasets.
 
+IMPORTANT: Default graph formats don't contain information about property cardinality, so it is up to the graph
+provider to choose the appropriate one. You will see a warning message if the chosen cardinality is SINGLE
+while your graph input contains multiple values for that property.
+
 In general, TinkerPop recommends that users examine the native bulk import/export tools of the graph implementation
 that they choose. Those tools will often outperform the `io()`-step and perhaps be easier to use with a greater
 feature set. That said, graph providers do have the option to optimize `io()` to back it with their own
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
index 3cd76f2b0f..701121f63e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
@@ -27,8 +27,14 @@ 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.empty.EmptyGraph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 
@@ -43,6 +49,8 @@ import java.util.function.Function;
  */
 public interface Attachable<V> {
 
+    Logger logger = LoggerFactory.getLogger(Attachable.class);
+
     /**
      * Get the raw object trying to be attached.
      *
@@ -291,12 +299,21 @@ public interface Attachable<V> {
             final Vertex vertex = hostGraph.features().vertex().willAllowId(baseVertex.id()) ?
                     hostGraph.addVertex(T.id, baseVertex.id(), T.label, baseVertex.label()) :
                     hostGraph.addVertex(T.label, baseVertex.label());
-            baseVertex.properties().forEachRemaining(vp -> {
-                final VertexProperty vertexProperty = hostGraph.features().vertex().properties().willAllowId(vp.id()) ?
-                        vertex.property(hostGraph.features().vertex().getCardinality(vp.key()), vp.key(), vp.value(), T.id, vp.id()) :
-                        vertex.property(hostGraph.features().vertex().getCardinality(vp.key()), vp.key(), vp.value());
-                vp.properties().forEachRemaining(p -> vertexProperty.property(p.key(), p.value()));
-            });
+            final Map<String, List<VertexProperty<Object>>> propertyMap = new HashMap<>();
+            baseVertex.properties().forEachRemaining(vp -> propertyMap.computeIfAbsent(vp.key(), k -> new ArrayList<>()).add(vp));
+            for (Map.Entry<String, List<VertexProperty<Object>>> entry : propertyMap.entrySet()) {
+                final VertexProperty.Cardinality cardinality = hostGraph.features().vertex().getCardinality(entry.getKey());
+                if (VertexProperty.Cardinality.single == cardinality && entry.getValue().size() > 1) {
+                    logger.warn("{} has SINGLE cardinality but with more than one value: {}. Only last value will be retained.",
+                        entry.getKey(), entry.getValue());
+                }
+                for (VertexProperty<Object> vp : entry.getValue()) {
+                    final VertexProperty<Object> vertexProperty = hostGraph.features().vertex().properties().willAllowId(vp.id()) ?
+                        vertex.property(cardinality, vp.key(), vp.value(), T.id, vp.id()) :
+                        vertex.property(cardinality, vp.key(), vp.value());
+                    vp.properties().forEachRemaining(p -> vertexProperty.property(p.key(), p.value()));
+                }
+            }
             return vertex;
         }