Repository: neo4j-contrib/neo4j-apoc-procedures
Pull request #31 (2016-05-10 14:17:53)

Flatmap


Patch:
diff --git a/src/main/java/apoc/map/Maps.java b/src/main/java/apoc/map/Maps.java
index a64f502cb..1f56e3ffa 100644
--- a/src/main/java/apoc/map/Maps.java
+++ b/src/main/java/apoc/map/Maps.java
@@ -5,7 +5,6 @@ import apoc.result.MapResult;
 import org.neo4j.graphdb.GraphDatabaseService;
 import org.neo4j.procedure.Context;
 import org.neo4j.procedure.Name;
-import org.neo4j.procedure.PerformsWrites;
 import org.neo4j.procedure.Procedure;
 
 import java.util.*;
@@ -56,7 +55,6 @@ public class Maps {
     }
 
     @Procedure
-    @PerformsWrites
     @Description("apoc.map.setKey(map,key,value)")
     public Stream<MapResult> setKey(@Name("map") Map<String,Object> map, @Name("key") String key, @Name("value") Object value) {
         LinkedHashMap<String, Object> res = new LinkedHashMap<>(map);
@@ -78,4 +76,23 @@ public class Maps {
         }
         return Stream.of(new MapResult(res));
     }
+
+    @Procedure
+    @Description("apoc.map.flatten(map) yield map - flattens nested items in map using dot notation")
+    public Stream<MapResult> flatten(@Name("map") Map<String, Object> map) {
+        Map<String, Object> flattenedMap = new HashMap<>();
+        flattenMapRecursively(flattenedMap, map, "");
+        return Stream.of(new MapResult(flattenedMap));
+    }
+
+    private void flattenMapRecursively(Map<String, Object> flattenedMap, Map<String, Object> map, String prefix) {
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+             if (entry.getValue() instanceof Map) {
+                 flattenMapRecursively(flattenedMap, (Map<String, Object>) entry.getValue(), prefix + entry.getKey() + ".");
+             } else {
+                 flattenedMap.put(prefix + entry.getKey(), entry.getValue());
+             }
+        }
+    }
+
 }


Test patch:
diff --git a/src/test/java/apoc/map/MapsTest.java b/src/test/java/apoc/map/MapsTest.java
index 72aa8e12c..e935dd2eb 100644
--- a/src/test/java/apoc/map/MapsTest.java
+++ b/src/test/java/apoc/map/MapsTest.java
@@ -7,6 +7,8 @@ import org.junit.Test;
 import org.neo4j.graphdb.GraphDatabaseService;
 import org.neo4j.test.TestGraphDatabaseFactory;
 
+import java.util.Map;
+
 import static apoc.util.MapUtil.map;
 import static org.junit.Assert.*;
 
@@ -54,4 +56,20 @@ public class MapsTest {
             assertEquals(map("a",1L),r.get("value"));
         });
     }
+
+    @Test
+    public void testFlatten() {
+        Map<String, Object> nestedMap = map("somekey", "someValue", "somenumeric", 123);
+        nestedMap = map("anotherkey", "anotherValue", "nested", nestedMap);
+        Map<String, Object> map = map("string", "value", "int", 10, "nested", nestedMap);
+
+        TestUtil.testCall(db, "CALL apoc.map.flatten({map})", map("map", map), (r) -> {
+            Map<String, Object> resultMap = (Map<String, Object>)r.get("value");
+            assertEquals(map("string", "value",
+                    "int", 10,
+                    "nested.anotherkey", "anotherValue",
+                    "nested.nested.somekey", "someValue",
+                    "nested.nested.somenumeric", 123), resultMap);
+        });
+    }
 }