From 4f4a1de8ddddc2731d83b0b5ea5f1146dcbba720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Wed, 14 Aug 2024 15:29:07 +0200 Subject: [PATCH 01/11] NodeProperty is a record --- .../Neo4jDatabaseNodePropertyWriter.java | 9 ++++----- .../WriteNodePropertiesApplication.java | 4 ++-- .../WriteNodePropertiesApplicationTest.java | 20 +++++++++---------- .../write/NativeNodePropertyExporterTest.java | 4 ++-- .../write/NativeNodePropertyExporter.java | 12 ++++++----- .../neo4j/gds/core/write/NodeProperty.java | 15 ++++++-------- .../ResultStoreNodePropertyExporter.java | 9 ++++----- .../ResultStoreNodePropertyExporterTest.java | 6 +++--- .../java/org/neo4j/gds/GraphStoreUpdater.java | 11 +++++----- ...dePropertiesComputationResultConsumer.java | 6 +++--- ...opertiesComputationResultConsumerTest.java | 4 ++-- .../neo4j/gds/WriteProcCancellationTest.java | 4 ++-- 12 files changed, 50 insertions(+), 54 deletions(-) diff --git a/applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/Neo4jDatabaseNodePropertyWriter.java b/applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/Neo4jDatabaseNodePropertyWriter.java index ea901026ad..c3a21124fd 100644 --- a/applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/Neo4jDatabaseNodePropertyWriter.java +++ b/applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/Neo4jDatabaseNodePropertyWriter.java @@ -34,7 +34,6 @@ import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker; import org.neo4j.gds.core.utils.progress.tasks.TaskProgressTracker; -import org.neo4j.gds.core.write.ImmutableNodeProperty; import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.core.write.NodePropertyExporter; import org.neo4j.gds.core.write.NodePropertyExporterBuilder; @@ -72,7 +71,7 @@ static NodePropertiesWritten writeNodeProperty( TerminationFlag terminationFlag, Log log ) { - var nodeProperties = List.of(ImmutableNodeProperty.of(writeProperty, nodePropertyValues)); + var nodeProperties = List.of(new NodeProperty(writeProperty, nodePropertyValues)); var propertiesWritten = new MutableLong(); @@ -143,7 +142,7 @@ private static void validatePropertiesCanBeWritten( var unexpectedProperties = nodeProperties .stream() .filter(nodeProperty -> { - var propertySchema = propertySchemas.get(nodeProperty.propertyKey()); + var propertySchema = propertySchemas.get(nodeProperty.key()); if (propertySchema == null) { // We are executing an algorithm write mode and the property we are writing is // not in the GraphStore, therefore we do not perform any more checks @@ -155,8 +154,8 @@ private static void validatePropertiesCanBeWritten( .map( nodeProperty -> formatWithLocale( "NodeProperty{propertyKey=%s, propertyState=%s}", - nodeProperty.propertyKey(), - propertySchemas.get(nodeProperty.propertyKey()).state() + nodeProperty.key(), + propertySchemas.get(nodeProperty.key()).state() ) ) .collect(Collectors.toList()); diff --git a/applications/graph-store-catalog/src/main/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplication.java b/applications/graph-store-catalog/src/main/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplication.java index 4b6fd6bce5..c81fd9fbf5 100644 --- a/applications/graph-store-catalog/src/main/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplication.java +++ b/applications/graph-store-catalog/src/main/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplication.java @@ -31,7 +31,7 @@ import org.neo4j.gds.core.utils.progress.tasks.TaskProgressTracker; import org.neo4j.gds.core.utils.progress.tasks.Tasks; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; -import org.neo4j.gds.core.write.ImmutableNodeProperty; +import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.core.write.NodePropertyExporter; import org.neo4j.gds.core.write.NodePropertyExporterBuilder; import org.neo4j.gds.logging.Log; @@ -138,7 +138,7 @@ private static long writeNodeProperties( var writeNodeProperties = config.nodeProperties() .stream() .map( - nodePropertyKey -> ImmutableNodeProperty.of( + nodePropertyKey -> NodeProperty.of( nodePropertyKey.writeProperty(), subGraph.nodeProperties(nodePropertyKey.nodeProperty()) ) diff --git a/applications/graph-store-catalog/src/test/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplicationTest.java b/applications/graph-store-catalog/src/test/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplicationTest.java index 377b1a669b..efb7abae6d 100644 --- a/applications/graph-store-catalog/src/test/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplicationTest.java +++ b/applications/graph-store-catalog/src/test/java/org/neo4j/gds/applications/graphstorecatalog/WriteNodePropertiesApplicationTest.java @@ -143,8 +143,8 @@ void writeNodeProperties(Object nodeLabels, String displayName) { verify(nodePropertyExporterMock, times(1)).write(captor.capture()); verifyNoMoreInteractions(nodePropertyExporterMock); assertThat(captor.getValue()).hasSize(2).satisfiesExactlyInAnyOrder( - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp1"), - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp2") + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp1"), + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp2") ); } @@ -190,8 +190,8 @@ void writeNodePropertiesForLabel() { verify(nodePropertyExporterMock, times(1)).write(captor.capture()); verifyNoMoreInteractions(nodePropertyExporterMock); assertThat(captor.getValue()).hasSize(2).satisfiesExactlyInAnyOrder( - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp1"), - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp2") + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp1"), + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp2") ); } @@ -228,8 +228,8 @@ void writeNodePropertiesForLabelSubset() { verify(nodePropertyExporterMock, times(1)).write(captor.capture()); verifyNoMoreInteractions(nodePropertyExporterMock); assertThat(captor.getValue()).hasSize(2).satisfiesExactlyInAnyOrder( - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp1"), - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp2") + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp1"), + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp2") ); } @@ -265,7 +265,7 @@ void shouldRenameSingleProperly() { verifyNoMoreInteractions(nodePropertyExporterMock); assertThat(captor.getValue()) .hasSize(1) - .satisfiesExactly(nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("foo")); + .satisfiesExactly(nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("foo")); } @Test @@ -303,9 +303,9 @@ void shouldRenameMultipleProperties() { assertThat(captor.getValue()) .hasSize(3) .satisfiesExactlyInAnyOrder( - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("foo"), - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("bar"), - nodeProperty -> assertThat(nodeProperty.propertyKey()).isEqualTo("nodeProp1") + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("foo"), + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("bar"), + nodeProperty -> assertThat(nodeProperty.key()).isEqualTo("nodeProp1") ); } } diff --git a/core-write/src/integrationTest/java/org/neo4j/gds/core/write/NativeNodePropertyExporterTest.java b/core-write/src/integrationTest/java/org/neo4j/gds/core/write/NativeNodePropertyExporterTest.java index 4f8e8438cc..1cb22b43d8 100644 --- a/core-write/src/integrationTest/java/org/neo4j/gds/core/write/NativeNodePropertyExporterTest.java +++ b/core-write/src/integrationTest/java/org/neo4j/gds/core/write/NativeNodePropertyExporterTest.java @@ -116,8 +116,8 @@ void exportMultipleNodeProperties() { double[] doubleData = {123D, 142D, 184D}; List nodeProperties = Arrays.asList( - ImmutableNodeProperty.of("newProp1", new LongTestPropertyValues(nodeId -> intData[(int) nodeId])), - ImmutableNodeProperty.of("newProp2", new DoubleTestPropertyValues(nodeId -> doubleData[(int) nodeId])) + NodeProperty.of("newProp1", new LongTestPropertyValues(nodeId -> intData[(int) nodeId])), + NodeProperty.of("newProp2", new DoubleTestPropertyValues(nodeId -> doubleData[(int) nodeId])) ); exporter.write(nodeProperties); diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java index c07d5ee295..6cf1079bfb 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java @@ -60,13 +60,15 @@ public static NodePropertyExporterBuilder builder(TransactionContext transaction @SuppressWarnings("immutables:subtype") @ValueClass - public interface ResolvedNodeProperty extends NodeProperty { + public interface ResolvedNodeProperty { + String propertyKey(); + NodePropertyValues properties(); int propertyToken(); static ResolvedNodeProperty of(NodeProperty nodeProperty, int propertyToken) { return ImmutableResolvedNodeProperty.of( - nodeProperty.propertyKey(), - nodeProperty.properties(), + nodeProperty.key(), + nodeProperty.values(), propertyToken ); } @@ -97,7 +99,7 @@ protected NativeNodePropertyExporter( @Override public void write(String property, NodePropertyValues properties) { - write(ImmutableNodeProperty.of(property, properties)); + write(NodeProperty.of(property, properties)); } @Override @@ -115,7 +117,7 @@ private static NativeNodePropertyExporter.ResolvedNodeProperty resolveWith(NodeP @Override public void write(Collection nodeProperties) { var resolvedNodeProperties = nodeProperties.stream() - .map(desc -> resolveWith(desc, getOrCreatePropertyToken(desc.propertyKey()))) + .map(desc -> resolveWith(desc, getOrCreatePropertyToken(desc.key()))) .collect(Collectors.toList()); progressTracker.beginSubTask(nodeCount); diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/NodeProperty.java b/core-write/src/main/java/org/neo4j/gds/core/write/NodeProperty.java index 574995249f..9087693159 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/NodeProperty.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/NodeProperty.java @@ -19,16 +19,13 @@ */ package org.neo4j.gds.core.write; -import org.neo4j.gds.annotation.ValueClass; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -@ValueClass -public interface NodeProperty { - String propertyKey(); - - NodePropertyValues properties(); - - static NodeProperty of(String propertyKey, NodePropertyValues properties) { - return ImmutableNodeProperty.of(propertyKey, properties); +public record NodeProperty( + String key, + NodePropertyValues values +) { + public static NodeProperty of(String key, NodePropertyValues values) { + return new NodeProperty(key, values); } } diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporter.java b/core-write/src/main/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporter.java index db761886b6..2ae006eeae 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporter.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporter.java @@ -23,7 +23,6 @@ import org.neo4j.gds.api.ResultStoreEntry; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.gds.core.utils.progress.JobId; -import org.neo4j.gds.core.write.ImmutableNodeProperty; import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.core.write.NodePropertyExporter; @@ -49,7 +48,7 @@ public class ResultStoreNodePropertyExporter implements NodePropertyExporter { @Override public void write(String property, NodePropertyValues properties) { - write(ImmutableNodeProperty.of(property, properties)); + write(NodeProperty.of(property, properties)); } @Override @@ -62,9 +61,9 @@ public void write(Collection nodeProperties) { var propertyKeys = new ArrayList(); var propertyValues = new ArrayList(); nodeProperties.forEach(nodeProperty -> { - propertyKeys.add(nodeProperty.propertyKey()); - propertyValues.add(nodeProperty.properties()); - writtenProperties += nodeProperty.properties().nodeCount(); + propertyKeys.add(nodeProperty.key()); + propertyValues.add(nodeProperty.values()); + writtenProperties += nodeProperty.values().nodeCount(); }); resultStore.add(jobId, new ResultStoreEntry.NodeProperties(nodeLabels, propertyKeys, propertyValues, toOriginalId)); diff --git a/core-write/src/test/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporterTest.java b/core-write/src/test/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporterTest.java index 489a8a760f..892d6f5168 100644 --- a/core-write/src/test/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporterTest.java +++ b/core-write/src/test/java/org/neo4j/gds/core/write/resultstore/ResultStoreNodePropertyExporterTest.java @@ -24,7 +24,7 @@ import org.neo4j.gds.api.ResultStoreEntry; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.gds.core.utils.progress.JobId; -import org.neo4j.gds.core.write.ImmutableNodeProperty; +import org.neo4j.gds.core.write.NodeProperty; import java.util.List; import java.util.function.LongUnaryOperator; @@ -73,8 +73,8 @@ void shouldWriteMultipleNodePropertiesToResultStore() { var nodePropertyExporter = new ResultStoreNodePropertyExporter(jobId, resultStore, List.of(PROJECT_ALL), toOriginalId); nodePropertyExporter.write(List.of( - ImmutableNodeProperty.of("prop1", nodePropertyValues1), - ImmutableNodeProperty.of("prop2", nodePropertyValues2) + NodeProperty.of("prop1", nodePropertyValues1), + NodeProperty.of("prop2", nodePropertyValues2) ) ); diff --git a/proc/common/src/main/java/org/neo4j/gds/GraphStoreUpdater.java b/proc/common/src/main/java/org/neo4j/gds/GraphStoreUpdater.java index 568a5fcd05..968eaac6a2 100644 --- a/proc/common/src/main/java/org/neo4j/gds/GraphStoreUpdater.java +++ b/proc/common/src/main/java/org/neo4j/gds/GraphStoreUpdater.java @@ -23,7 +23,6 @@ import org.neo4j.gds.api.GraphStore; import org.neo4j.gds.config.MutateNodePropertyConfig; import org.neo4j.gds.core.huge.FilteredNodePropertyValues; -import org.neo4j.gds.core.write.ImmutableNodeProperty; import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.executor.ComputationResult; import org.neo4j.gds.executor.ExecutionContext; @@ -70,10 +69,10 @@ public static void updateGraphStore( .asNodeFilteredGraph() .map(filteredGraph -> nodePropertyList .stream() - .map(nodeProperty -> ImmutableNodeProperty.of( - nodeProperty.propertyKey(), + .map(nodeProperty -> NodeProperty.of( + nodeProperty.key(), FilteredNodePropertyValues.OriginalToFilteredNodePropertyValues.create( - nodeProperty.properties(), + nodeProperty.values(), filteredGraph ) )) @@ -86,8 +85,8 @@ public static void updateGraphStore( maybeTranslatedProperties.forEach(nodeProperty -> graphStore.addNodeProperty( new HashSet<>(labelsToUpdate), - nodeProperty.propertyKey(), - nodeProperty.properties() + nodeProperty.key(), + nodeProperty.values() )); resultBuilder.withNodePropertiesWritten(maybeTranslatedProperties.size() * graph.nodeCount()); diff --git a/proc/common/src/main/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumer.java b/proc/common/src/main/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumer.java index 91a22e5847..f3987a78a4 100644 --- a/proc/common/src/main/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumer.java +++ b/proc/common/src/main/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumer.java @@ -76,7 +76,7 @@ private static void validatePropertiesCanBeWritten( var unexpectedProperties = nodeProperties .stream() .filter(nodeProperty -> { - var propertySchema = propertySchemas.get(nodeProperty.propertyKey()); + var propertySchema = propertySchemas.get(nodeProperty.key()); if (propertySchema == null) { // We are executing an algorithm write mode and the property we are writing is // not in the GraphStore, therefore we do not perform any more checks @@ -88,8 +88,8 @@ private static void validatePropertiesCanBeWritten( .map( nodeProperty -> formatWithLocale( "NodeProperty{propertyKey=%s, propertyState=%s}", - nodeProperty.propertyKey(), - propertySchemas.get(nodeProperty.propertyKey()).state() + nodeProperty.key(), + propertySchemas.get(nodeProperty.key()).state() ) ) .toList(); diff --git a/proc/common/src/test/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumerTest.java b/proc/common/src/test/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumerTest.java index ad1e13f559..cdb5649686 100644 --- a/proc/common/src/test/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumerTest.java +++ b/proc/common/src/test/java/org/neo4j/gds/WriteNodePropertiesComputationResultConsumerTest.java @@ -48,8 +48,8 @@ import org.neo4j.gds.core.utils.progress.EmptyTaskRegistryFactory; import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker; import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory; -import org.neo4j.gds.core.write.ImmutableNodeProperty; import org.neo4j.gds.core.write.NativeNodePropertiesExporterBuilder; +import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.executor.ComputationResult; import org.neo4j.gds.executor.ExecutionContext; import org.neo4j.gds.executor.ImmutableComputationResult; @@ -132,7 +132,7 @@ private void executeWrite( ); var writeConsumer = new WriteNodePropertiesComputationResultConsumer( (computationResult, executionContext) -> new TestAlgoResultBuilder(), - computationResult -> List.of(ImmutableNodeProperty.of( + computationResult -> List.of(NodeProperty.of( propertyKey, graphStore.nodeProperty(propertyKey).values() )), diff --git a/proc/common/src/test/java/org/neo4j/gds/WriteProcCancellationTest.java b/proc/common/src/test/java/org/neo4j/gds/WriteProcCancellationTest.java index 9ab42d89a5..a369d7f7ba 100644 --- a/proc/common/src/test/java/org/neo4j/gds/WriteProcCancellationTest.java +++ b/proc/common/src/test/java/org/neo4j/gds/WriteProcCancellationTest.java @@ -33,8 +33,8 @@ import org.neo4j.gds.core.utils.progress.TaskRegistry; import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker; import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory; -import org.neo4j.gds.core.write.ImmutableNodeProperty; import org.neo4j.gds.core.write.NativeNodePropertiesExporterBuilder; +import org.neo4j.gds.core.write.NodeProperty; import org.neo4j.gds.executor.ImmutableComputationResult; import org.neo4j.gds.executor.ImmutableExecutionContext; import org.neo4j.gds.gdl.GdlFactory; @@ -73,7 +73,7 @@ public long nodeCount() { return 42; } }; - var nodeProperty = ImmutableNodeProperty.of("prop", nodeProperties); + var nodeProperty = NodeProperty.of("prop", nodeProperties); try (var tx = db.beginTx()) { From 91d9ce08a4b686b9ac3cb4fd111a200677cfefe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Mon, 26 Aug 2024 12:19:19 +0200 Subject: [PATCH 02/11] ResolvedNodeProperty is a record --- .../gds/core/write/NativeNodePropertyExporter.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java index 6cf1079bfb..d4e8732bf7 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java @@ -19,7 +19,6 @@ */ package org.neo4j.gds.core.write; -import org.neo4j.gds.annotation.ValueClass; import org.neo4j.gds.api.IdMap; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.gds.compat.Neo4jProxy; @@ -58,18 +57,13 @@ public static NodePropertyExporterBuilder builder(TransactionContext transaction .withTerminationFlag(terminationFlag); } - @SuppressWarnings("immutables:subtype") - @ValueClass - public interface ResolvedNodeProperty { - String propertyKey(); - NodePropertyValues properties(); - int propertyToken(); + record ResolvedNodeProperty(int propertyToken, String propertyKey, NodePropertyValues properties) { static ResolvedNodeProperty of(NodeProperty nodeProperty, int propertyToken) { - return ImmutableResolvedNodeProperty.of( + return new ResolvedNodeProperty( + propertyToken, nodeProperty.key(), - nodeProperty.values(), - propertyToken + nodeProperty.values() ); } } From 856de13e3dde8526c7381fc432e438fcf63d53c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Thu, 22 Aug 2024 09:49:37 +0200 Subject: [PATCH 03/11] Node property func doesn't need Value --- .../main/java/org/neo4j/gds/functions/NodePropertyFunc.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/proc/common/src/main/java/org/neo4j/gds/functions/NodePropertyFunc.java b/proc/common/src/main/java/org/neo4j/gds/functions/NodePropertyFunc.java index d131ffb8dc..a52728a585 100644 --- a/proc/common/src/main/java/org/neo4j/gds/functions/NodePropertyFunc.java +++ b/proc/common/src/main/java/org/neo4j/gds/functions/NodePropertyFunc.java @@ -32,8 +32,6 @@ import org.neo4j.procedure.Description; import org.neo4j.procedure.Name; import org.neo4j.procedure.UserFunction; -import org.neo4j.values.storable.DoubleArray; -import org.neo4j.values.storable.FloatArray; import java.util.Objects; @@ -112,10 +110,10 @@ public Object nodeProperty( double propertyValue = propertyValues.doubleValue(internalId); return Double.isNaN(propertyValue) ? null : propertyValue; case DOUBLE_ARRAY: - double[] doubleArray = ((DoubleArray)propertyValues.value(internalId)).asObjectCopy(); + double[] doubleArray = propertyValues.doubleArrayValue(internalId); return doubleArray == null ? new double[] {} : doubleArray; case FLOAT_ARRAY: - float[] floatArray = ((FloatArray)propertyValues.value(internalId)).asObjectCopy(); + float[] floatArray = propertyValues.floatArrayValue(internalId); return floatArray == null ? new float[] {} : floatArray; case LONG_ARRAY: long[] longArray = propertyValues.longArrayValue(internalId); From ac0ec9e39572c0b1c4cfb038a4f2716dce287a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Mon, 26 Aug 2024 12:48:59 +0200 Subject: [PATCH 04/11] Add Neo4j-specific node property values These will provide org.neo4j.values.storable.Value from GDS node proprty values, so that the latter can be Neo4j-agnostic. --- .../Neo4jDoubleArrayNodePropertyValues.java | 49 +++++++++++++++++++ .../Neo4jDoubleNodePropertyValues.java | 49 +++++++++++++++++++ .../Neo4jFloatArrayNodePropertyValues.java | 49 +++++++++++++++++++ .../Neo4jLongArrayNodePropertyValues.java | 49 +++++++++++++++++++ .../Neo4jLongNodePropertyValues.java | 48 ++++++++++++++++++ .../construction/Neo4jNodePropertyValues.java | 27 ++++++++++ .../Neo4jNodePropertyValuesUtil.java | 46 +++++++++++++++++ 7 files changed, 317 insertions(+) create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java new file mode 100644 index 0000000000..5ebe8892e7 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class Neo4jDoubleArrayNodePropertyValues implements DoubleArrayNodePropertyValues, Neo4jNodePropertyValues { + + private final DoubleArrayNodePropertyValues internal; + + public Neo4jDoubleArrayNodePropertyValues(DoubleArrayNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + var value = doubleArrayValue(nodeId); + return value == null ? null : Values.doubleArray(value); + } + + @Override + public double[] doubleArrayValue(long nodeId) { + return internal.doubleArrayValue(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java new file mode 100644 index 0000000000..5218213b0b --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class Neo4jDoubleNodePropertyValues implements DoubleNodePropertyValues, Neo4jNodePropertyValues { + + private final DoubleNodePropertyValues internal; + + public Neo4jDoubleNodePropertyValues(DoubleNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + var value = doubleValue(nodeId); + return Double.isNaN(value) ? null : Values.doubleValue(value); + } + + @Override + public double doubleValue(long nodeId) { + return internal.doubleValue(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java new file mode 100644 index 0000000000..abd00d6216 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class Neo4jFloatArrayNodePropertyValues implements FloatArrayNodePropertyValues, Neo4jNodePropertyValues { + + private final FloatArrayNodePropertyValues internal; + + public Neo4jFloatArrayNodePropertyValues(FloatArrayNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + var value = floatArrayValue(nodeId); + return value == null ? null : Values.floatArray(value); + } + + @Override + public float[] floatArrayValue(long nodeId) { + return internal.floatArrayValue(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java new file mode 100644 index 0000000000..f6f482f378 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class Neo4jLongArrayNodePropertyValues implements LongArrayNodePropertyValues, Neo4jNodePropertyValues { + + private final LongArrayNodePropertyValues internal; + + public Neo4jLongArrayNodePropertyValues(LongArrayNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + var value = longArrayValue(nodeId); + return value == null ? null : Values.longArray(value); + } + + @Override + public long[] longArrayValue(long nodeId) { + return internal.longArrayValue(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java new file mode 100644 index 0000000000..ee0aa22747 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class Neo4jLongNodePropertyValues implements LongNodePropertyValues, Neo4jNodePropertyValues { + + private final LongNodePropertyValues internal; + + public Neo4jLongNodePropertyValues(LongNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + return Values.longValue(longValue(nodeId)); + } + + @Override + public long longValue(long nodeId) { + return internal.longValue(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java new file mode 100644 index 0000000000..e988c10363 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; +import org.neo4j.values.storable.Value; + +public interface Neo4jNodePropertyValues extends NodePropertyValues { + Value value(long nodeId); +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java new file mode 100644 index 0000000000..c1338067f8 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.loading.construction; + +import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; + +public final class Neo4jNodePropertyValuesUtil { + + public static Neo4jNodePropertyValues of(NodePropertyValues internal) { + return switch(internal.valueType()) { + case DOUBLE -> new Neo4jDoubleNodePropertyValues((DoubleNodePropertyValues) internal); + case LONG -> new Neo4jLongNodePropertyValues((LongNodePropertyValues) internal); + case FLOAT_ARRAY -> new Neo4jFloatArrayNodePropertyValues((FloatArrayNodePropertyValues) internal); + case DOUBLE_ARRAY -> new Neo4jDoubleArrayNodePropertyValues((DoubleArrayNodePropertyValues) internal); + case LONG_ARRAY -> new Neo4jLongArrayNodePropertyValues((LongArrayNodePropertyValues) internal); +// case STRING -> null; +// case UNTYPED_ARRAY -> null; +// case UNKNOWN -> null; + default -> throw new IllegalArgumentException("Exporting values of type " + internal.valueType().csvName() + " is not supported."); + }; + } + + private Neo4jNodePropertyValuesUtil() {} +} From 77c06f275d13588043f8ff555974f0f5d6d019ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Mon, 26 Aug 2024 12:58:44 +0200 Subject: [PATCH 05/11] Move neo4j values to better package --- .../main/java/org/neo4j/gds/projection/ReadNodeLabels.java | 2 +- .../org/neo4j/gds/legacycypherprojection/NodeSubscriber.java | 2 +- .../construction => values}/CypherNodeLabelTokens.java | 4 +++- .../Neo4jDoubleArrayNodePropertyValues.java | 2 +- .../Neo4jDoubleNodePropertyValues.java | 2 +- .../Neo4jFloatArrayNodePropertyValues.java | 2 +- .../Neo4jLongArrayNodePropertyValues.java | 2 +- .../construction => values}/Neo4jLongNodePropertyValues.java | 2 +- .../construction => values}/Neo4jNodePropertyValues.java | 2 +- .../construction => values}/Neo4jNodePropertyValuesUtil.java | 2 +- 10 files changed, 12 insertions(+), 10 deletions(-) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/CypherNodeLabelTokens.java (95%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jDoubleArrayNodePropertyValues.java (97%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jDoubleNodePropertyValues.java (96%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jFloatArrayNodePropertyValues.java (96%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jLongArrayNodePropertyValues.java (96%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jLongNodePropertyValues.java (96%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jNodePropertyValues.java (95%) rename neo4j-values/src/main/java/org/neo4j/gds/{core/loading/construction => values}/Neo4jNodePropertyValuesUtil.java (97%) diff --git a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ReadNodeLabels.java b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ReadNodeLabels.java index 3119aba623..84a25995a5 100644 --- a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ReadNodeLabels.java +++ b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ReadNodeLabels.java @@ -19,9 +19,9 @@ */ package org.neo4j.gds.projection; -import org.neo4j.gds.core.loading.construction.CypherNodeLabelTokens; import org.neo4j.gds.core.loading.construction.NodeLabelToken; import org.neo4j.gds.core.loading.construction.NodeLabelTokens; +import org.neo4j.gds.values.CypherNodeLabelTokens; import org.neo4j.values.AnyValue; import org.neo4j.values.SequenceValue; import org.neo4j.values.storable.BooleanValue; diff --git a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/NodeSubscriber.java b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/NodeSubscriber.java index 0a9cc458ae..d86f592b56 100644 --- a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/NodeSubscriber.java +++ b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/NodeSubscriber.java @@ -20,9 +20,9 @@ package org.neo4j.gds.legacycypherprojection; import org.neo4j.gds.core.loading.ValueConverter; -import org.neo4j.gds.core.loading.construction.CypherNodeLabelTokens; import org.neo4j.gds.core.loading.construction.NodesBuilder; import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker; +import org.neo4j.gds.values.CypherNodeLabelTokens; import org.neo4j.graphdb.QueryStatistics; import org.neo4j.values.AnyValue; import org.neo4j.values.SequenceValue; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/CypherNodeLabelTokens.java b/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java similarity index 95% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/CypherNodeLabelTokens.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java index eec4719155..98aac9d6ed 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/CypherNodeLabelTokens.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java @@ -17,11 +17,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.eclipse.collections.api.block.function.primitive.ObjectIntToObjectFunction; import org.jetbrains.annotations.NotNull; import org.neo4j.gds.NodeLabel; +import org.neo4j.gds.core.loading.construction.NodeLabelToken; +import org.neo4j.gds.core.loading.construction.NodeLabelTokens; import org.neo4j.values.SequenceValue; import org.neo4j.values.storable.TextArray; import org.neo4j.values.storable.TextValue; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java similarity index 97% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java index 5ebe8892e7..491b047675 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java similarity index 96% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java index 5218213b0b..c5526cc5c2 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jDoubleNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java similarity index 96% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java index abd00d6216..e517bd7929 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jFloatArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java similarity index 96% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java index f6f482f378..5fd037c696 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java similarity index 96% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java index ee0aa22747..10601c97ff 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jLongNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java similarity index 95% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java index e988c10363..f625423976 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; diff --git a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java similarity index 97% rename from neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java rename to neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java index c1338067f8..6f57cb815d 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/core/loading/construction/Neo4jNodePropertyValuesUtil.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.core.loading.construction; +package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; From a8164e48f0d6385d54c45dd4836c03776b917619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Mon, 26 Aug 2024 14:49:10 +0200 Subject: [PATCH 06/11] Some write paths use Neo4j property types --- core-write/build.gradle | 1 + .../write/NativeNodePropertyExporter.java | 14 ++++--- .../gds/core/write/Neo4jNodeProperty.java | 39 +++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 core-write/src/main/java/org/neo4j/gds/core/write/Neo4jNodeProperty.java diff --git a/core-write/build.gradle b/core-write/build.gradle index 9fdd2456d4..90c3f7af82 100644 --- a/core-write/build.gradle +++ b/core-write/build.gradle @@ -24,6 +24,7 @@ dependencies { implementation project(':annotations') implementation project(':core') // TODO move core.concurrency out of core to not depend on whole core implementation project(':core-utils') + implementation project(':neo4j-values') implementation project(':progress-tracking') implementation project(':graph-schema-api') implementation project(':transaction') diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java index d4e8732bf7..2697e089cd 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java @@ -31,6 +31,8 @@ import org.neo4j.gds.termination.TerminationFlag; import org.neo4j.gds.transaction.TransactionContext; import org.neo4j.gds.utils.StatementApi; +import org.neo4j.gds.values.Neo4jNodePropertyValues; +import org.neo4j.gds.values.Neo4jNodePropertyValuesUtil; import org.neo4j.values.storable.Value; import java.util.Collection; @@ -57,13 +59,13 @@ public static NodePropertyExporterBuilder builder(TransactionContext transaction .withTerminationFlag(terminationFlag); } - record ResolvedNodeProperty(int propertyToken, String propertyKey, NodePropertyValues properties) { + record ResolvedNodeProperty(int token, String key, Neo4jNodePropertyValues values) { - static ResolvedNodeProperty of(NodeProperty nodeProperty, int propertyToken) { + static ResolvedNodeProperty of(NodeProperty nodeProperty, int token) { return new ResolvedNodeProperty( - propertyToken, + token, nodeProperty.key(), - nodeProperty.values() + Neo4jNodePropertyValuesUtil.of(nodeProperty.values()) ); } } @@ -141,8 +143,8 @@ private void writeParallel(Iterable nodeProperties) { private void doWrite(Iterable nodeProperties, Write ops, long nodeId) throws Exception { for (ResolvedNodeProperty nodeProperty : nodeProperties) { - int propertyId = nodeProperty.propertyToken(); - final Value prop = nodeProperty.properties().value(nodeId); + int propertyId = nodeProperty.token(); + final Value prop = nodeProperty.values().value(nodeId); if (prop != null) { ops.nodeSetProperty( toOriginalId.applyAsLong(nodeId), diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/Neo4jNodeProperty.java b/core-write/src/main/java/org/neo4j/gds/core/write/Neo4jNodeProperty.java new file mode 100644 index 0000000000..e651b10315 --- /dev/null +++ b/core-write/src/main/java/org/neo4j/gds/core/write/Neo4jNodeProperty.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.core.write; + +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; +import org.neo4j.gds.values.Neo4jNodePropertyValues; +import org.neo4j.gds.values.Neo4jNodePropertyValuesUtil; + +public record Neo4jNodeProperty( + String key, + Neo4jNodePropertyValues values +) { + public static Neo4jNodeProperty of(NodeProperty nodeProperty) { + return new Neo4jNodeProperty( + nodeProperty.key(), + Neo4jNodePropertyValuesUtil.of(nodeProperty.values()) + ); + } + public static Neo4jNodeProperty of(String key, NodePropertyValues values) { + return new Neo4jNodeProperty(key, Neo4jNodePropertyValuesUtil.of(values)); + } +} From 6ee19ff889d94bb3530d4a4e6c79ad94b1955e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Mon, 26 Aug 2024 18:15:14 +0200 Subject: [PATCH 07/11] Rename to neo4jValue to reveal usage of value --- .../org/neo4j/gds/core/write/NativeNodePropertyExporter.java | 2 +- .../neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java | 5 +++++ .../org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java | 5 +++++ .../neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java | 5 +++++ .../neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java | 5 +++++ .../org/neo4j/gds/values/Neo4jLongNodePropertyValues.java | 5 +++++ .../java/org/neo4j/gds/values/Neo4jNodePropertyValues.java | 2 ++ 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java index 2697e089cd..f97b2fe988 100644 --- a/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java +++ b/core-write/src/main/java/org/neo4j/gds/core/write/NativeNodePropertyExporter.java @@ -144,7 +144,7 @@ private void writeParallel(Iterable nodeProperties) { private void doWrite(Iterable nodeProperties, Write ops, long nodeId) throws Exception { for (ResolvedNodeProperty nodeProperty : nodeProperties) { int propertyId = nodeProperty.token(); - final Value prop = nodeProperty.values().value(nodeId); + final Value prop = nodeProperty.values().neo4jValue(nodeId); if (prop != null) { ops.nodeSetProperty( toOriginalId.applyAsLong(nodeId), diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java index 491b047675..1285c1cd1b 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java @@ -33,6 +33,11 @@ public Neo4jDoubleArrayNodePropertyValues(DoubleArrayNodePropertyValues internal @Override public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { var value = doubleArrayValue(nodeId); return value == null ? null : Values.doubleArray(value); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java index c5526cc5c2..e4b499c89e 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java @@ -33,6 +33,11 @@ public Neo4jDoubleNodePropertyValues(DoubleNodePropertyValues internal) { @Override public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { var value = doubleValue(nodeId); return Double.isNaN(value) ? null : Values.doubleValue(value); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java index e517bd7929..63ba472812 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java @@ -33,6 +33,11 @@ public Neo4jFloatArrayNodePropertyValues(FloatArrayNodePropertyValues internal) @Override public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { var value = floatArrayValue(nodeId); return value == null ? null : Values.floatArray(value); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java index 5fd037c696..ab1552a0f5 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java @@ -33,6 +33,11 @@ public Neo4jLongArrayNodePropertyValues(LongArrayNodePropertyValues internal) { @Override public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { var value = longArrayValue(nodeId); return value == null ? null : Values.longArray(value); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java index 10601c97ff..fe8e6f6b46 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java @@ -33,6 +33,11 @@ public Neo4jLongNodePropertyValues(LongNodePropertyValues internal) { @Override public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { return Values.longValue(longValue(nodeId)); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java index f625423976..210f7c6562 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValues.java @@ -24,4 +24,6 @@ public interface Neo4jNodePropertyValues extends NodePropertyValues { Value value(long nodeId); + + Value neo4jValue(long nodeId); } From 4aac0dec8fa8b4dff84d44b8d3bfac47b57a7b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Tue, 27 Aug 2024 11:51:26 +0200 Subject: [PATCH 08/11] Community result filtering without neo4j values Co-Authored-By: Paul Horn --- .../community/CommunityCompanion.java | 42 ++++++++++--------- .../ConsecutiveLongNodePropertyValues.java | 18 ++++++-- .../LongIfChangedNodePropertyValues.java | 27 ++++++++---- .../community/CommunityCompanionTest.java | 6 ++- .../FilteredNodePropertyValuesMarker.java | 23 ++++++++++ .../values/Neo4jLongNodePropertyValues.java | 14 ++++++- .../values/Neo4jNodePropertyValuesUtil.java | 3 +- 7 files changed, 98 insertions(+), 35 deletions(-) create mode 100644 core/src/main/java/org/neo4j/gds/api/properties/nodes/FilteredNodePropertyValuesMarker.java diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java index ca7c0937ef..c4da49e9a6 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java @@ -22,6 +22,7 @@ import org.eclipse.collections.api.block.function.primitive.LongToObjectFunction; import org.neo4j.gds.api.Graph; import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodeProperty; @@ -30,8 +31,8 @@ import org.neo4j.gds.core.concurrency.Concurrency; import org.neo4j.gds.core.concurrency.DefaultPool; import org.neo4j.gds.result.CommunityStatistics; -import org.neo4j.values.storable.LongValue; import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; import java.util.ArrayList; import java.util.List; @@ -65,13 +66,13 @@ public static NodePropertyValues nodePropertyValues( Supplier seedPropertySupplier ) { + if (consecutiveIds) { + return new ConsecutiveLongNodePropertyValues(nodeProperties); + } if (isIncremental && resultProperty.equals(seedProperty)) { nodeProperties = LongIfChangedNodePropertyValues.of(seedPropertySupplier.get(), nodeProperties); } - if (consecutiveIds) { - return new ConsecutiveLongNodePropertyValues(nodeProperties); - } return nodeProperties; } @@ -160,7 +161,7 @@ static List> arrayMatrixToListMatrix(boolean shouldCompute, double[ return null; } - private static class CommunitySizeFilter implements LongNodePropertyValues { + private static class CommunitySizeFilter implements LongNodePropertyValues, FilteredNodePropertyValuesMarker { private final LongNodePropertyValues properties; @@ -183,31 +184,32 @@ public long nodeCount() { return properties.nodeCount(); } - @Override - public long longValue(long nodeId) { - return properties.longValue(nodeId); - } - /** - * Returning null indicates that the value is not written to Neo4j. + * Returning Long.MIN_VALUE indicates that the value should not be written to Neo4j. *

* The filter is applied in the latest stage before writing to Neo4j. - * Since the wrapped node properties may have additional logic in value(), + * Since the wrapped node properties may have additional logic in longValue(), * we need to check if they already filtered the value. Only in the case * where the wrapped properties pass on the value, we can apply a filter. */ @Override - public Value value(long nodeId) { - var value = properties.value(nodeId); + public long longValue(long nodeId) { + var longValue = properties.longValue(nodeId); + // did the wrapped properties filter out the value? + if (longValue == Long.MIN_VALUE) { + return Long.MIN_VALUE; + } + // apply our own filter + return isCommunityMinSizeMet(longValue) ? longValue : Long.MIN_VALUE; + } - if (value == null) { + @Override + public Value value(long nodeId) { + long value = longValue(nodeId); + if (value == Long.MIN_VALUE) { return null; } - - // This cast is safe since we handle LongNodeProperties. - var communityId = ((LongValue) value).longValue(); - - return isCommunityMinSizeMet(communityId) ? value : null; + return Values.longValue(value); } @Override diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java index d6489b8306..9d23fac066 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java @@ -19,6 +19,7 @@ */ package org.neo4j.gds.algorithms.community; +import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.collections.ha.HugeLongArray; import org.neo4j.gds.core.utils.paged.HugeLongLongMap; @@ -26,7 +27,7 @@ import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; -public class ConsecutiveLongNodePropertyValues implements LongNodePropertyValues { +public class ConsecutiveLongNodePropertyValues implements LongNodePropertyValues, FilteredNodePropertyValuesMarker { private static final long MAPPING_SIZE_QUOTIENT = 10L; private static final long NO_VALUE = -1L; @@ -59,9 +60,21 @@ public ConsecutiveLongNodePropertyValues(LongNodePropertyValues inputProperties) } } + /** + * Returning Long.MIN_VALUE indicates that the value should not be written to Neo4j. + *

+ * The filter is applied in the latest stage before writing to Neo4j. + * Since the wrapped node properties may have additional logic in longValue(), + * we need to check if they already filtered the value. Only in the case + * where the wrapped properties pass on the value, we can apply a filter. + */ @Override public long longValue(long nodeId) { - return communities.get(nodeId); + long l = communities.get(nodeId); + if (l == NO_VALUE) { + return Long.MIN_VALUE; + } + return l; } @Override @@ -75,7 +88,6 @@ public Value value(long nodeId) { return Values.longValue(communities.get(nodeId)); } return null; - } @Override diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java index d6176844d0..62d4623e4b 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java @@ -21,6 +21,7 @@ import org.neo4j.gds.api.PropertyState; import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodeProperty; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; @@ -29,7 +30,7 @@ import static org.neo4j.gds.utils.StringFormatting.formatWithLocale; -public final class LongIfChangedNodePropertyValues implements LongNodePropertyValues { +public final class LongIfChangedNodePropertyValues implements LongNodePropertyValues, FilteredNodePropertyValuesMarker { private final NodePropertyValues seedProperties; private final NodePropertyValues newProperties; @@ -62,17 +63,29 @@ private LongIfChangedNodePropertyValues( this.newProperties = newProperties; } + /** + * Returning Long.MIN_VALUE indicates that the value should not be written to Neo4j. + *

+ * The filter is applied in the latest stage before writing to Neo4j. + * Since the wrapped node properties may have additional logic in longValue(), + * we need to check if they already filtered the value. Only in the case + * where the wrapped properties pass on the value, we can apply a filter. + */ @Override public long longValue(long nodeId) { - return newProperties.longValue(nodeId); + var seedValue = seedProperties.longValue(nodeId); + var writeValue = newProperties.longValue(nodeId); + + return (seedValue != writeValue) ? writeValue : Long.MIN_VALUE; } @Override public Value value(long nodeId) { - long seedValue = seedProperties.longValue(nodeId); - long writeValue = newProperties.longValue(nodeId); - - return seedValue == Long.MIN_VALUE || (seedValue != writeValue) ? Values.longValue(writeValue) : null; + var value = longValue(nodeId); + if (value == Long.MIN_VALUE) { + return null; + } + return Values.longValue(value); } @Override @@ -84,7 +97,7 @@ public long nodeCount() { public boolean hasValue(long nodeId) { long seedValue = seedProperties.longValue(nodeId); long writeValue = newProperties.longValue(nodeId); - return seedValue == Long.MIN_VALUE || (seedValue != writeValue) ? true : false; + return seedValue == Long.MIN_VALUE || (seedValue != writeValue); } } diff --git a/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java b/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java index 9740e017a5..634d0d775d 100644 --- a/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java +++ b/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java @@ -101,8 +101,9 @@ void shouldReturnOnlyChangedProperties() { ); assertThat(result).isInstanceOf(LongIfChangedNodePropertyValues.class); + // properties that have not changed signalled by Long.MIN_VALUE and null for (long i = 0; i < result.nodeCount(); i++) { - assertThat(result.longValue(i)).isEqualTo(inputProperties.longValue(i)); + assertThat(result.longValue(i)).isEqualTo(Long.MIN_VALUE); assertThat(result.value(i)).isNull(); } } @@ -123,7 +124,8 @@ void shouldRestrictCommunitySize() { for (long i = 0L; i < result.nodeCount(); i++) { if (i < 5) { - assertThat(result.longValue(i)).isEqualTo(inputProperties.longValue(i)); + // properties that have not changed signalled by Long.MIN_VALUE and null + assertThat(result.longValue(i)).isEqualTo(Long.MIN_VALUE); assertThat(result.value(i)).isNull(); } else { assertThat(result.longValue(i)).isEqualTo(inputProperties.longValue(i)); diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/FilteredNodePropertyValuesMarker.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/FilteredNodePropertyValuesMarker.java new file mode 100644 index 0000000000..8c5616b0b6 --- /dev/null +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/FilteredNodePropertyValuesMarker.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.api.properties.nodes; + +public interface FilteredNodePropertyValuesMarker { +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java index fe8e6f6b46..155a9a1814 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java @@ -26,9 +26,15 @@ public class Neo4jLongNodePropertyValues implements LongNodePropertyValues, Neo4jNodePropertyValues { private final LongNodePropertyValues internal; + private final boolean deafultIsNull; - public Neo4jLongNodePropertyValues(LongNodePropertyValues internal) { + public Neo4jLongNodePropertyValues(LongNodePropertyValues internal, boolean deafultIsNull) { this.internal = internal; + this.deafultIsNull = deafultIsNull; + } + + public Neo4jLongNodePropertyValues(LongNodePropertyValues internal) { + this(internal, false); } @Override @@ -38,7 +44,11 @@ public Value value(long nodeId) { @Override public Value neo4jValue(long nodeId) { - return Values.longValue(longValue(nodeId)); + long value = longValue(nodeId); + if (deafultIsNull && value == Long.MIN_VALUE) { + return null; + } + return Values.longValue(value); } @Override diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java index 6f57cb815d..9a42f9ffb7 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java @@ -21,6 +21,7 @@ import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; @@ -31,7 +32,7 @@ public final class Neo4jNodePropertyValuesUtil { public static Neo4jNodePropertyValues of(NodePropertyValues internal) { return switch(internal.valueType()) { case DOUBLE -> new Neo4jDoubleNodePropertyValues((DoubleNodePropertyValues) internal); - case LONG -> new Neo4jLongNodePropertyValues((LongNodePropertyValues) internal); + case LONG -> new Neo4jLongNodePropertyValues((LongNodePropertyValues) internal, internal instanceof FilteredNodePropertyValuesMarker); case FLOAT_ARRAY -> new Neo4jFloatArrayNodePropertyValues((FloatArrayNodePropertyValues) internal); case DOUBLE_ARRAY -> new Neo4jDoubleArrayNodePropertyValues((DoubleArrayNodePropertyValues) internal); case LONG_ARRAY -> new Neo4jLongArrayNodePropertyValues((LongArrayNodePropertyValues) internal); From 676780e343d10686de929a8ddedbb0d6e46add37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Tue, 27 Aug 2024 12:36:16 +0200 Subject: [PATCH 09/11] Remove Neo4j values from node property values --- .../community/CommunityCompanion.java | 11 ----------- .../ConsecutiveLongNodePropertyValues.java | 10 ---------- .../LongIfChangedNodePropertyValues.java | 11 ----------- .../hashgnn/EmbeddingsToNodePropertyValues.java | 16 +++++++--------- .../metrics/NullCheckingNodePropertyValues.java | 8 -------- .../community/CommunityCompanionTest.java | 8 ++------ .../nodes/DoubleArrayNodePropertyValues.java | 8 -------- .../nodes/DoubleNodePropertyValues.java | 8 -------- .../nodes/FloatArrayNodePropertyValues.java | 8 -------- .../nodes/LongArrayNodePropertyValues.java | 8 -------- .../nodes/LongNodePropertyValues.java | 7 ------- .../properties/nodes/NodePropertyValues.java | 3 --- .../core/huge/FilteredNodePropertyValues.java | 17 ----------------- .../neo4j/gds/core/loading/NullPropertyMap.java | 12 ------------ .../core/io/file/GraphStoreNodeVisitorTest.java | 2 +- 15 files changed, 10 insertions(+), 127 deletions(-) diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java index c4da49e9a6..4cc44224fa 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/CommunityCompanion.java @@ -31,8 +31,6 @@ import org.neo4j.gds.core.concurrency.Concurrency; import org.neo4j.gds.core.concurrency.DefaultPool; import org.neo4j.gds.result.CommunityStatistics; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.ArrayList; import java.util.List; @@ -203,15 +201,6 @@ public long longValue(long nodeId) { return isCommunityMinSizeMet(longValue) ? longValue : Long.MIN_VALUE; } - @Override - public Value value(long nodeId) { - long value = longValue(nodeId); - if (value == Long.MIN_VALUE) { - return null; - } - return Values.longValue(value); - } - @Override public boolean hasValue(long nodeId) { return isCommunityMinSizeMet(properties.longValue(nodeId)); diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java index 9d23fac066..216ac2eea7 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/ConsecutiveLongNodePropertyValues.java @@ -24,8 +24,6 @@ import org.neo4j.gds.collections.ha.HugeLongArray; import org.neo4j.gds.core.utils.paged.HugeLongLongMap; import org.neo4j.gds.mem.BitUtil; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; public class ConsecutiveLongNodePropertyValues implements LongNodePropertyValues, FilteredNodePropertyValuesMarker { @@ -82,14 +80,6 @@ public boolean hasValue(long nodeId) { return communities.get(nodeId) != NO_VALUE; } - @Override - public Value value(long nodeId) { - if (hasValue(nodeId)) { - return Values.longValue(communities.get(nodeId)); - } - return null; - } - @Override public long nodeCount() { return communities.size(); diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java index 62d4623e4b..a19dc43174 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/community/LongIfChangedNodePropertyValues.java @@ -25,8 +25,6 @@ import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodeProperty; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import static org.neo4j.gds.utils.StringFormatting.formatWithLocale; @@ -79,15 +77,6 @@ public long longValue(long nodeId) { return (seedValue != writeValue) ? writeValue : Long.MIN_VALUE; } - @Override - public Value value(long nodeId) { - var value = longValue(nodeId); - if (value == Long.MIN_VALUE) { - return null; - } - return Values.longValue(value); - } - @Override public long nodeCount() { return Math.max(newProperties.nodeCount(), seedProperties.nodeCount()); diff --git a/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java index 64cdddcced..e18c1a2436 100644 --- a/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java @@ -22,10 +22,8 @@ import org.neo4j.gds.api.nodeproperties.ValueType; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -import org.neo4j.gds.core.utils.paged.HugeAtomicBitSet; import org.neo4j.gds.collections.ha.HugeObjectArray; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; +import org.neo4j.gds.core.utils.paged.HugeAtomicBitSet; import java.util.Optional; @@ -83,12 +81,12 @@ public Object getObject(long nodeId) { return bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension); } - @Override - public Value value(long nodeId) { - // as Boolean array is not an official property type in GDS we transform to double[]. - // We use the same data type as in the dense case. - return Values.doubleArray(bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension)); - } +// @Override +// public Value value(long nodeId) { +// // as Boolean array is not an official property type in GDS we transform to double[]. +// // We use the same data type as in the dense case. +// return Values.doubleArray(bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension)); +// } @Override public Optional dimension() { diff --git a/algo/src/main/java/org/neo4j/gds/similarity/knn/metrics/NullCheckingNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/similarity/knn/metrics/NullCheckingNodePropertyValues.java index a7014eedba..d15142be7f 100644 --- a/algo/src/main/java/org/neo4j/gds/similarity/knn/metrics/NullCheckingNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/similarity/knn/metrics/NullCheckingNodePropertyValues.java @@ -23,7 +23,6 @@ import org.neo4j.gds.api.IdMap; import org.neo4j.gds.api.nodeproperties.ValueType; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -import org.neo4j.values.storable.Value; import java.util.Optional; @@ -85,13 +84,6 @@ public Optional dimension() { return properties.dimension(); } - @Override - public Value value(long nodeId) { - var value = properties.value(nodeId); - check(nodeId, value); - return value; - } - @Override public long nodeCount() { return properties.nodeCount(); diff --git a/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java b/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java index 634d0d775d..9bee745bf8 100644 --- a/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java +++ b/algo/src/test/java/org/neo4j/gds/algorithms/community/CommunityCompanionTest.java @@ -101,10 +101,9 @@ void shouldReturnOnlyChangedProperties() { ); assertThat(result).isInstanceOf(LongIfChangedNodePropertyValues.class); - // properties that have not changed signalled by Long.MIN_VALUE and null + // properties that have not changed signalled by Long.MIN_VALUE for (long i = 0; i < result.nodeCount(); i++) { assertThat(result.longValue(i)).isEqualTo(Long.MIN_VALUE); - assertThat(result.value(i)).isNull(); } } @@ -124,12 +123,10 @@ void shouldRestrictCommunitySize() { for (long i = 0L; i < result.nodeCount(); i++) { if (i < 5) { - // properties that have not changed signalled by Long.MIN_VALUE and null + // properties that have not changed signalled by Long.MIN_VALUE assertThat(result.longValue(i)).isEqualTo(Long.MIN_VALUE); - assertThat(result.value(i)).isNull(); } else { assertThat(result.longValue(i)).isEqualTo(inputProperties.longValue(i)); - assertThat(result.value(i).asObject()).isEqualTo(5L); } } } @@ -155,7 +152,6 @@ void shouldWorkWithMinComponentAndConsecutive() { assertThat(result.hasValue(i)).isFalse(); } else { assertThat(result.hasValue(i)).isTrue(); - assertThat(result.value(i).asObject()).isEqualTo(returnedValues[(int) i]); } } diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleArrayNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleArrayNodePropertyValues.java index 67859c1e1d..57c7f981ec 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleArrayNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleArrayNodePropertyValues.java @@ -20,8 +20,6 @@ package org.neo4j.gds.api.properties.nodes; import org.neo4j.gds.api.nodeproperties.ValueType; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; @@ -50,12 +48,6 @@ default Object getObject(long nodeId) { return doubleArrayValue(nodeId); } - @Override - default Value value(long nodeId) { - var value = doubleArrayValue(nodeId); - return value == null ? null : Values.doubleArray(value); - } - @Override default ValueType valueType() { return ValueType.DOUBLE_ARRAY; diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleNodePropertyValues.java index aef847a02e..5e9daafcdf 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/DoubleNodePropertyValues.java @@ -20,8 +20,6 @@ package org.neo4j.gds.api.properties.nodes; import org.neo4j.gds.api.nodeproperties.ValueType; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; import java.util.OptionalDouble; @@ -37,12 +35,6 @@ default Object getObject(long nodeId) { return doubleValue(nodeId); } - @Override - default Value value(long nodeId) { - var value = doubleValue(nodeId); - return Double.isNaN(value) ? null : Values.doubleValue(value); - } - @Override default ValueType valueType() { return ValueType.DOUBLE; diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/FloatArrayNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/FloatArrayNodePropertyValues.java index 4b6b13c17b..820043f38e 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/FloatArrayNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/FloatArrayNodePropertyValues.java @@ -20,8 +20,6 @@ package org.neo4j.gds.api.properties.nodes; import org.neo4j.gds.api.nodeproperties.ValueType; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; @@ -51,12 +49,6 @@ default Object getObject(long nodeId) { return floatArrayValue(nodeId); } - @Override - default Value value(long nodeId) { - var value = floatArrayValue(nodeId); - return value == null ? null : Values.floatArray(value); - } - @Override default ValueType valueType() { return ValueType.FLOAT_ARRAY; diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongArrayNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongArrayNodePropertyValues.java index b6ca891e40..393cace196 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongArrayNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongArrayNodePropertyValues.java @@ -20,8 +20,6 @@ package org.neo4j.gds.api.properties.nodes; import org.neo4j.gds.api.nodeproperties.ValueType; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; @@ -35,12 +33,6 @@ default Object getObject(long nodeId) { return longArrayValue(nodeId); } - @Override - default Value value(long nodeId) { - var value = longArrayValue(nodeId); - return value == null ? null : Values.longArray(value); - } - @Override default ValueType valueType() { return ValueType.LONG_ARRAY; diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongNodePropertyValues.java index 96f5fd6c74..f559014f75 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/LongNodePropertyValues.java @@ -22,8 +22,6 @@ import org.neo4j.gds.api.DefaultValue; import org.neo4j.gds.api.ValueConversion; import org.neo4j.gds.api.nodeproperties.ValueType; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; import java.util.OptionalLong; @@ -39,11 +37,6 @@ default Object getObject(long nodeId) { return longValue(nodeId); } - @Override - default Value value(long nodeId) { - return Values.longValue(longValue(nodeId)); - } - @Override default ValueType valueType() { return ValueType.LONG; diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/NodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/NodePropertyValues.java index fedd02a568..408093023a 100644 --- a/core/src/main/java/org/neo4j/gds/api/properties/nodes/NodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/NodePropertyValues.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.Nullable; import org.neo4j.gds.api.nodeproperties.ValueType; import org.neo4j.gds.api.properties.PropertyValues; -import org.neo4j.values.storable.Value; import java.util.Optional; import java.util.OptionalDouble; @@ -58,8 +57,6 @@ default long[] longArrayValue(long nodeId) { @Nullable Object getObject(long nodeId); - Value value(long nodeId); - long nodeCount(); /** diff --git a/core/src/main/java/org/neo4j/gds/core/huge/FilteredNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/core/huge/FilteredNodePropertyValues.java index a81487f86a..13ccc0813c 100644 --- a/core/src/main/java/org/neo4j/gds/core/huge/FilteredNodePropertyValues.java +++ b/core/src/main/java/org/neo4j/gds/core/huge/FilteredNodePropertyValues.java @@ -24,8 +24,6 @@ import org.neo4j.gds.api.DefaultValue; import org.neo4j.gds.api.nodeproperties.ValueType; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; import java.util.OptionalDouble; @@ -72,11 +70,6 @@ public Object getObject(long nodeId) { return properties.getObject(translateId(nodeId)); } - @Override - public Value value(long nodeId) { - return properties.value(translateId(nodeId)); - } - @Override public ValueType valueType() { return properties.valueType(); @@ -235,16 +228,6 @@ public Object getObject(long nodeId) { return properties.getObject(translatedId); } - @Override - public Value value(long nodeId) { - long translatedId = translateId(nodeId); - - if (translatedId < 0) { - return Values.NO_VALUE; - } - return properties.value(translatedId); - } - @Override protected long translateId(long nodeId) { return graph.toFilteredNodeId(nodeId); diff --git a/core/src/main/java/org/neo4j/gds/core/loading/NullPropertyMap.java b/core/src/main/java/org/neo4j/gds/core/loading/NullPropertyMap.java index 84f00c9dd7..d86303b48b 100644 --- a/core/src/main/java/org/neo4j/gds/core/loading/NullPropertyMap.java +++ b/core/src/main/java/org/neo4j/gds/core/loading/NullPropertyMap.java @@ -22,8 +22,6 @@ import org.neo4j.gds.api.nodeproperties.ValueType; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import java.util.Optional; import java.util.OptionalDouble; @@ -55,11 +53,6 @@ public Object getObject(long nodeId) { return doubleValue(nodeId); } - @Override - public Value value(long nodeId) { - return Values.doubleValue(defaultValue); - } - @Override public ValueType valueType() { return ValueType.DOUBLE; @@ -91,11 +84,6 @@ public Object getObject(long nodeId) { return longValue(nodeId); } - @Override - public Value value(long nodeId) { - return Values.longValue(defaultValue); - } - @Override public OptionalLong getMaxLongPropertyValue() { return OptionalLong.empty(); diff --git a/io/core/src/test/java/org/neo4j/gds/core/io/file/GraphStoreNodeVisitorTest.java b/io/core/src/test/java/org/neo4j/gds/core/io/file/GraphStoreNodeVisitorTest.java index f19e179482..a30c22f6f2 100644 --- a/io/core/src/test/java/org/neo4j/gds/core/io/file/GraphStoreNodeVisitorTest.java +++ b/io/core/src/test/java/org/neo4j/gds/core/io/file/GraphStoreNodeVisitorTest.java @@ -70,7 +70,7 @@ void shouldAddNodesToNodesBuilder() { nodeVisitor.labels(nodeLabels.stream().map(NodeLabel::name).toArray(String[]::new)); var propertyKeys = graphStore.nodePropertyKeys(nodeLabels); for (String propertyKey : propertyKeys) { - nodeVisitor.property(propertyKey, graph.nodeProperties(propertyKey).value(nodeId).asObject()); + nodeVisitor.property(propertyKey, graph.nodeProperties(propertyKey).getObject(nodeId)); } nodeVisitor.endOfEntity(); return true; From f499af29adee0b974a3f7ae4cd0eeb2910a839e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Tue, 27 Aug 2024 13:30:14 +0200 Subject: [PATCH 10/11] Make BinaryArrayNPV adaptable with Neo4j values --- .../EmbeddingsToNodePropertyValues.java | 84 +--------------- .../nodes/BinaryArrayNodePropertyValues.java | 99 +++++++++++++++++++ .../Neo4jBinaryArrayNodePropertyValues.java | 68 +++++++++++++ .../values/Neo4jNodePropertyValuesUtil.java | 4 + 4 files changed, 172 insertions(+), 83 deletions(-) create mode 100644 core/src/main/java/org/neo4j/gds/api/properties/nodes/BinaryArrayNodePropertyValues.java create mode 100644 neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jBinaryArrayNodePropertyValues.java diff --git a/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java b/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java index e18c1a2436..cf247b818d 100644 --- a/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java +++ b/algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/EmbeddingsToNodePropertyValues.java @@ -19,14 +19,12 @@ */ package org.neo4j.gds.embeddings.hashgnn; -import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.api.properties.nodes.BinaryArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.gds.collections.ha.HugeObjectArray; import org.neo4j.gds.core.utils.paged.HugeAtomicBitSet; -import java.util.Optional; - public final class EmbeddingsToNodePropertyValues { private EmbeddingsToNodePropertyValues() {} @@ -47,84 +45,4 @@ public long nodeCount() { static NodePropertyValues fromBinary(HugeObjectArray binaryEmbeddings, int embeddingDimension) { return new BinaryArrayNodePropertyValues(binaryEmbeddings, embeddingDimension); } - - private static class BinaryArrayNodePropertyValues implements NodePropertyValues { - - private final HugeObjectArray binaryEmbeddings; - private final int embeddingDimension; - - BinaryArrayNodePropertyValues( - HugeObjectArray binaryEmbeddings, - int embeddingDimension - ) { - this.binaryEmbeddings = binaryEmbeddings; - this.embeddingDimension = embeddingDimension; - } - - @Override - public double[] doubleArrayValue(long nodeId) { - return bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension); - } - - @Override - public float[] floatArrayValue(long nodeId) { - return bitSetToFloatArray(binaryEmbeddings.get(nodeId), embeddingDimension); - } - - @Override - public long[] longArrayValue(long nodeId) { - return bitSetToLongArray(binaryEmbeddings.get(nodeId), embeddingDimension); - } - - @Override - public Object getObject(long nodeId) { - return bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension); - } - -// @Override -// public Value value(long nodeId) { -// // as Boolean array is not an official property type in GDS we transform to double[]. -// // We use the same data type as in the dense case. -// return Values.doubleArray(bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension)); -// } - - @Override - public Optional dimension() { - return Optional.of(embeddingDimension); - } - - @Override - public ValueType valueType() { - return ValueType.DOUBLE_ARRAY; - } - - @Override - public long nodeCount() { - return binaryEmbeddings.size(); - } - - private static double[] bitSetToDoubleArray(HugeAtomicBitSet bitSet, int dimension) { - var array = new double[dimension]; - bitSet.forEachSetBit(bit -> { - array[(int) bit] = 1.0; - }); - return array; - } - - private static float[] bitSetToFloatArray(HugeAtomicBitSet bitSet, int dimension) { - var array = new float[dimension]; - bitSet.forEachSetBit(bit -> { - array[(int) bit] = 1.0f; - }); - return array; - } - - private static long[] bitSetToLongArray(HugeAtomicBitSet bitSet, int dimension) { - var array = new long[dimension]; - bitSet.forEachSetBit(bit -> { - array[(int) bit] = 1; - }); - return array; - } - } } diff --git a/core/src/main/java/org/neo4j/gds/api/properties/nodes/BinaryArrayNodePropertyValues.java b/core/src/main/java/org/neo4j/gds/api/properties/nodes/BinaryArrayNodePropertyValues.java new file mode 100644 index 0000000000..781ef7f58a --- /dev/null +++ b/core/src/main/java/org/neo4j/gds/api/properties/nodes/BinaryArrayNodePropertyValues.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.api.properties.nodes; + +import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.collections.ha.HugeObjectArray; +import org.neo4j.gds.core.utils.paged.HugeAtomicBitSet; + +import java.util.Optional; + +public class BinaryArrayNodePropertyValues implements NodePropertyValues { + + private final HugeObjectArray binaryEmbeddings; + private final int embeddingDimension; + + public BinaryArrayNodePropertyValues( + HugeObjectArray binaryEmbeddings, + int embeddingDimension + ) { + this.binaryEmbeddings = binaryEmbeddings; + this.embeddingDimension = embeddingDimension; + } + + @Override + public double[] doubleArrayValue(long nodeId) { + return bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension); + } + + @Override + public float[] floatArrayValue(long nodeId) { + return bitSetToFloatArray(binaryEmbeddings.get(nodeId), embeddingDimension); + } + + @Override + public long[] longArrayValue(long nodeId) { + return bitSetToLongArray(binaryEmbeddings.get(nodeId), embeddingDimension); + } + + @Override + public Object getObject(long nodeId) { + return bitSetToDoubleArray(binaryEmbeddings.get(nodeId), embeddingDimension); + } + + @Override + public Optional dimension() { + return Optional.of(embeddingDimension); + } + + @Override + public ValueType valueType() { + return ValueType.DOUBLE_ARRAY; + } + + @Override + public long nodeCount() { + return binaryEmbeddings.size(); + } + + private static double[] bitSetToDoubleArray(HugeAtomicBitSet bitSet, int dimension) { + var array = new double[dimension]; + bitSet.forEachSetBit(bit -> { + array[(int) bit] = 1.0; + }); + return array; + } + + private static float[] bitSetToFloatArray(HugeAtomicBitSet bitSet, int dimension) { + var array = new float[dimension]; + bitSet.forEachSetBit(bit -> { + array[(int) bit] = 1.0f; + }); + return array; + } + + private static long[] bitSetToLongArray(HugeAtomicBitSet bitSet, int dimension) { + var array = new long[dimension]; + bitSet.forEachSetBit(bit -> { + array[(int) bit] = 1; + }); + return array; + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jBinaryArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jBinaryArrayNodePropertyValues.java new file mode 100644 index 0000000000..23c070f483 --- /dev/null +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jBinaryArrayNodePropertyValues.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.values; + +import org.jetbrains.annotations.Nullable; +import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.api.properties.nodes.BinaryArrayNodePropertyValues; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +import java.util.Optional; + +public class Neo4jBinaryArrayNodePropertyValues implements Neo4jNodePropertyValues { + private final BinaryArrayNodePropertyValues internal; + + Neo4jBinaryArrayNodePropertyValues(BinaryArrayNodePropertyValues internal) { + this.internal = internal; + } + + @Override + public Value value(long nodeId) { + return neo4jValue(nodeId); + } + + @Override + public Value neo4jValue(long nodeId) { + // as Boolean array is not an official property type in GDS we transform to double[]. + // We use the same data type as in the dense case. + return Values.doubleArray(internal.doubleArrayValue(nodeId)); + } + + @Override + public @Nullable Object getObject(long nodeId) { + return internal.getObject(nodeId); + } + + @Override + public long nodeCount() { + return internal.nodeCount(); + } + + @Override + public Optional dimension() { + return internal.dimension(); + } + + @Override + public ValueType valueType() { + return internal.valueType(); + } +} diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java index 9a42f9ffb7..7122f07f0f 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java @@ -19,6 +19,7 @@ */ package org.neo4j.gds.values; +import org.neo4j.gds.api.properties.nodes.BinaryArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; @@ -30,6 +31,9 @@ public final class Neo4jNodePropertyValuesUtil { public static Neo4jNodePropertyValues of(NodePropertyValues internal) { + if (internal instanceof BinaryArrayNodePropertyValues asBinaryArrayNodePropertyValues) { + return new Neo4jBinaryArrayNodePropertyValues(asBinaryArrayNodePropertyValues); + } return switch(internal.valueType()) { case DOUBLE -> new Neo4jDoubleNodePropertyValues((DoubleNodePropertyValues) internal); case LONG -> new Neo4jLongNodePropertyValues((LongNodePropertyValues) internal, internal instanceof FilteredNodePropertyValuesMarker); From 7e6812f3fcb683e8498c8cc6527aee721b0c6eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20J=C3=A4derberg?= Date: Tue, 27 Aug 2024 13:49:15 +0200 Subject: [PATCH 11/11] Relax typing to accept filtered NPValues --- .../Neo4jDoubleArrayNodePropertyValues.java | 5 +++-- .../gds/values/Neo4jDoubleNodePropertyValues.java | 5 +++-- .../values/Neo4jFloatArrayNodePropertyValues.java | 5 +++-- .../values/Neo4jLongArrayNodePropertyValues.java | 5 +++-- .../gds/values/Neo4jLongNodePropertyValues.java | 7 ++++--- .../gds/values/Neo4jNodePropertyValuesUtil.java | 15 +++++---------- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java index 1285c1cd1b..8bf57899f8 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleArrayNodePropertyValues.java @@ -20,14 +20,15 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; public class Neo4jDoubleArrayNodePropertyValues implements DoubleArrayNodePropertyValues, Neo4jNodePropertyValues { - private final DoubleArrayNodePropertyValues internal; + private final NodePropertyValues internal; - public Neo4jDoubleArrayNodePropertyValues(DoubleArrayNodePropertyValues internal) { + public Neo4jDoubleArrayNodePropertyValues(NodePropertyValues internal) { this.internal = internal; } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java index e4b499c89e..8795d31ad2 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jDoubleNodePropertyValues.java @@ -20,14 +20,15 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; public class Neo4jDoubleNodePropertyValues implements DoubleNodePropertyValues, Neo4jNodePropertyValues { - private final DoubleNodePropertyValues internal; + private final NodePropertyValues internal; - public Neo4jDoubleNodePropertyValues(DoubleNodePropertyValues internal) { + public Neo4jDoubleNodePropertyValues(NodePropertyValues internal) { this.internal = internal; } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java index 63ba472812..d1ef6a43c6 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jFloatArrayNodePropertyValues.java @@ -20,14 +20,15 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; public class Neo4jFloatArrayNodePropertyValues implements FloatArrayNodePropertyValues, Neo4jNodePropertyValues { - private final FloatArrayNodePropertyValues internal; + private final NodePropertyValues internal; - public Neo4jFloatArrayNodePropertyValues(FloatArrayNodePropertyValues internal) { + public Neo4jFloatArrayNodePropertyValues(NodePropertyValues internal) { this.internal = internal; } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java index ab1552a0f5..348597fbd3 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongArrayNodePropertyValues.java @@ -20,14 +20,15 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; public class Neo4jLongArrayNodePropertyValues implements LongArrayNodePropertyValues, Neo4jNodePropertyValues { - private final LongArrayNodePropertyValues internal; + private final NodePropertyValues internal; - public Neo4jLongArrayNodePropertyValues(LongArrayNodePropertyValues internal) { + public Neo4jLongArrayNodePropertyValues(NodePropertyValues internal) { this.internal = internal; } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java index 155a9a1814..1ec1076af2 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jLongNodePropertyValues.java @@ -20,20 +20,21 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; +import org.neo4j.gds.api.properties.nodes.NodePropertyValues; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; public class Neo4jLongNodePropertyValues implements LongNodePropertyValues, Neo4jNodePropertyValues { - private final LongNodePropertyValues internal; + private final NodePropertyValues internal; private final boolean deafultIsNull; - public Neo4jLongNodePropertyValues(LongNodePropertyValues internal, boolean deafultIsNull) { + public Neo4jLongNodePropertyValues(NodePropertyValues internal, boolean deafultIsNull) { this.internal = internal; this.deafultIsNull = deafultIsNull; } - public Neo4jLongNodePropertyValues(LongNodePropertyValues internal) { + public Neo4jLongNodePropertyValues(NodePropertyValues internal) { this(internal, false); } diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java index 7122f07f0f..aaac0e491d 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/Neo4jNodePropertyValuesUtil.java @@ -20,12 +20,7 @@ package org.neo4j.gds.values; import org.neo4j.gds.api.properties.nodes.BinaryArrayNodePropertyValues; -import org.neo4j.gds.api.properties.nodes.DoubleArrayNodePropertyValues; -import org.neo4j.gds.api.properties.nodes.DoubleNodePropertyValues; import org.neo4j.gds.api.properties.nodes.FilteredNodePropertyValuesMarker; -import org.neo4j.gds.api.properties.nodes.FloatArrayNodePropertyValues; -import org.neo4j.gds.api.properties.nodes.LongArrayNodePropertyValues; -import org.neo4j.gds.api.properties.nodes.LongNodePropertyValues; import org.neo4j.gds.api.properties.nodes.NodePropertyValues; public final class Neo4jNodePropertyValuesUtil { @@ -35,11 +30,11 @@ public static Neo4jNodePropertyValues of(NodePropertyValues internal) { return new Neo4jBinaryArrayNodePropertyValues(asBinaryArrayNodePropertyValues); } return switch(internal.valueType()) { - case DOUBLE -> new Neo4jDoubleNodePropertyValues((DoubleNodePropertyValues) internal); - case LONG -> new Neo4jLongNodePropertyValues((LongNodePropertyValues) internal, internal instanceof FilteredNodePropertyValuesMarker); - case FLOAT_ARRAY -> new Neo4jFloatArrayNodePropertyValues((FloatArrayNodePropertyValues) internal); - case DOUBLE_ARRAY -> new Neo4jDoubleArrayNodePropertyValues((DoubleArrayNodePropertyValues) internal); - case LONG_ARRAY -> new Neo4jLongArrayNodePropertyValues((LongArrayNodePropertyValues) internal); + case DOUBLE -> new Neo4jDoubleNodePropertyValues(internal); + case LONG -> new Neo4jLongNodePropertyValues(internal, internal instanceof FilteredNodePropertyValuesMarker); + case FLOAT_ARRAY -> new Neo4jFloatArrayNodePropertyValues(internal); + case DOUBLE_ARRAY -> new Neo4jDoubleArrayNodePropertyValues(internal); + case LONG_ARRAY -> new Neo4jLongArrayNodePropertyValues(internal); // case STRING -> null; // case UNTYPED_ARRAY -> null; // case UNKNOWN -> null;