From 951ed5a1006a16b5747a2263ec386d206672d3d7 Mon Sep 17 00:00:00 2001 From: Gemma Lamont Date: Thu, 2 Jan 2025 15:15:32 +0100 Subject: [PATCH] Add option to wrap a nodes id to the apoc.create.virtual.fromNode --- .../main/java/apoc/result/VirtualNode.java | 10 +++++++--- core/src/main/java/apoc/create/Create.java | 6 ++++-- .../src/test/java/apoc/create/CreateTest.java | 19 +++++++++++++++++++ .../resources/functions/common/functions.json | 8 +++++++- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/apoc/result/VirtualNode.java b/common/src/main/java/apoc/result/VirtualNode.java index f60479e7c..acabbbe4f 100644 --- a/common/src/main/java/apoc/result/VirtualNode.java +++ b/common/src/main/java/apoc/result/VirtualNode.java @@ -63,12 +63,12 @@ public VirtualNode(long nodeId) { this.elementId = null; } - public VirtualNode(Node node, List propertyNames) { + public VirtualNode(Node node, List propertyNames, boolean wrapNodeIDs) { Objects.requireNonNull(node, ERROR_NODE_NULL); final long id = node.getId(); // if node is already virtual, we return the same id - this.id = id < 0 ? id : -id - 1; - // to not overlap this ids with ids from VirtualNode(Label[] labels, Map props) + this.id = id < 0 || wrapNodeIDs ? id : -id - 1; + // to not overlap this nodes ids with ids from VirtualNode(Label[] labels, Map props) MIN_ID.updateAndGet(x -> Math.min(x, this.id)); this.labels.addAll(Util.labelStrings(node)); String[] keys = propertyNames.toArray(new String[propertyNames.size()]); @@ -76,6 +76,10 @@ public VirtualNode(Node node, List propertyNames) { this.elementId = node.getElementId(); } + public VirtualNode(Node node, List propertyNames) { + this(node, propertyNames, false); + } + public static VirtualNode from(Node node) { return new VirtualNode(node, Iterables.asList(node.getPropertyKeys())); } diff --git a/core/src/main/java/apoc/create/Create.java b/core/src/main/java/apoc/create/Create.java index 40deb4531..a66017b7b 100644 --- a/core/src/main/java/apoc/create/Create.java +++ b/core/src/main/java/apoc/create/Create.java @@ -232,8 +232,10 @@ public Node vNodeFunction( public Node virtualFromNodeFunction( @Name(value = "node", description = "The node to generate a virtual node from.") Node node, @Name(value = "propertyNames", description = "The properties to copy to the virtual node.") - List propertyNames) { - return new VirtualNode(node, propertyNames); + List propertyNames, + @Name(value = "config", defaultValue = "{}", description = "{ wrapNodeIds = false :: BOOLEAN }") + Map config) { + return new VirtualNode(node, propertyNames, Util.toBoolean(config.get("wrapNodeIds"))); } @Procedure("apoc.create.vNodes") diff --git a/core/src/test/java/apoc/create/CreateTest.java b/core/src/test/java/apoc/create/CreateTest.java index 51d36b92f..3c8fcac58 100644 --- a/core/src/test/java/apoc/create/CreateTest.java +++ b/core/src/test/java/apoc/create/CreateTest.java @@ -409,6 +409,25 @@ public void testVirtualFromNodeFunction() { Node node = (Node) row.get("node"); assertTrue(node.hasLabel(label("Person"))); + assertTrue(node.getId() < 0); + assertEquals("Vincent", node.getProperty("name")); + assertNull(node.getProperty("born")); + }); + } + + @Test + public void testVirtualFromNodeFunctionWithWrapping() { + testCall( + db, + """ + CREATE (n:Person{name:'Vincent', born: 1974} ) + RETURN apoc.create.virtual.fromNode(n, ['name'], { wrapNodeIds : true }) AS node + """, + (row) -> { + Node node = (Node) row.get("node"); + + assertTrue(node.hasLabel(label("Person"))); + assertTrue(node.getId() >= 0); assertEquals("Vincent", node.getProperty("name")); assertNull(node.getProperty("born")); }); diff --git a/core/src/test/resources/functions/common/functions.json b/core/src/test/resources/functions/common/functions.json index 38a8d23a5..d8c0560b5 100644 --- a/core/src/test/resources/functions/common/functions.json +++ b/core/src/test/resources/functions/common/functions.json @@ -1643,7 +1643,7 @@ }, { "isDeprecated" : false, "aggregating" : false, - "signature" : "apoc.create.virtual.fromNode(node :: NODE, propertyNames :: LIST) :: NODE", + "signature" : "apoc.create.virtual.fromNode(node :: NODE, propertyNames :: LIST, config = {} :: MAP) :: NODE", "name" : "apoc.create.virtual.fromNode", "description" : "Returns a virtual `NODE` from the given existing `NODE`. The virtual `NODE` only contains the requested properties.", "returnDescription" : "NODE", @@ -1660,6 +1660,12 @@ "description" : "The properties to copy to the virtual node.", "isDeprecated" : false, "type" : "LIST" + }, { + "name" : "config", + "description" : "{ wrapNodeIds = false :: BOOLEAN }", + "isDeprecated" : false, + "default" : "DefaultParameterValue{value={}, type=MAP}", + "type" : "MAP" } ] }, { "isDeprecated" : false,