Skip to content

Commit 3760663

Browse files
committed
migrate node classification mutate
1 parent a0e2ba7 commit 3760663

File tree

35 files changed

+962
-271
lines changed

35 files changed

+962
-271
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.applications.algorithms.machinery;
21+
22+
import org.neo4j.gds.api.Graph;
23+
import org.neo4j.gds.api.GraphStore;
24+
import org.neo4j.gds.applications.algorithms.metadata.NodePropertiesWritten;
25+
import org.neo4j.gds.config.AlgoBaseConfig;
26+
import org.neo4j.gds.core.huge.FilteredNodePropertyValues;
27+
import org.neo4j.gds.core.write.NodeProperty;
28+
import org.neo4j.gds.logging.Log;
29+
30+
import java.util.HashSet;
31+
import java.util.List;
32+
import java.util.stream.Collectors;
33+
34+
public class GraphStoreService {
35+
private final Log log;
36+
37+
public GraphStoreService(Log log) {
38+
this.log = log;
39+
}
40+
41+
public NodePropertiesWritten addNodeProperties(
42+
Graph graph,
43+
GraphStore graphStore,
44+
AlgoBaseConfig configuration,
45+
List<NodeProperty> nodeProperties
46+
) {
47+
var translatedProperties = translateProperties(graph, nodeProperties);
48+
49+
log.info("Updating in-memory graph store");
50+
var labelsToUpdate = configuration.nodeLabelIdentifiers(graphStore);
51+
52+
translatedProperties.forEach(nodeProperty -> graphStore.addNodeProperty(
53+
new HashSet<>(labelsToUpdate),
54+
nodeProperty.key(),
55+
nodeProperty.values()
56+
));
57+
58+
return new NodePropertiesWritten(translatedProperties.size() * graph.nodeCount());
59+
}
60+
61+
private List<NodeProperty> translateProperties(Graph graph, List<NodeProperty> nodeProperties) {
62+
return graph
63+
.asNodeFilteredGraph()
64+
.map(filteredGraph -> nodeProperties
65+
.stream()
66+
.map(nodeProperty -> NodeProperty.of(
67+
nodeProperty.key(),
68+
FilteredNodePropertyValues.OriginalToFilteredNodePropertyValues.create(
69+
nodeProperty.values(),
70+
filteredGraph
71+
)
72+
))
73+
.collect(Collectors.toList()))
74+
.orElse(nodeProperties);
75+
}
76+
}

applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/StandardLabel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020
package org.neo4j.gds.applications.algorithms.machinery;
2121

22-
record StandardLabel(String value) implements Label {
22+
public record StandardLabel(String value) implements Label {
2323
@Override
2424
public String asString() {
2525
return value;

applications/algorithms/similarity/src/main/java/org/neo4j/gds/applications/algorithms/similarity/SimilarityApplications.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.neo4j.gds.applications.algorithms.machinery.AlgorithmProcessingTemplateConvenience;
2525
import org.neo4j.gds.applications.algorithms.machinery.ProgressTrackerCreator;
2626
import org.neo4j.gds.applications.algorithms.machinery.RequestScopedDependencies;
27+
import org.neo4j.gds.applications.algorithms.machinery.WriteContext;
2728
import org.neo4j.gds.logging.Log;
2829

2930
public final class SimilarityApplications {
@@ -53,7 +54,7 @@ public static SimilarityApplications create(
5354
AlgorithmEstimationTemplate algorithmEstimationTemplate,
5455
AlgorithmProcessingTemplateConvenience algorithmProcessingTemplateConvenience,
5556
ProgressTrackerCreator progressTrackerCreator,
56-
WriteRelationshipService writeRelationshipService
57+
WriteContext writeContext
5758
) {
5859
var estimationModeFacade = new SimilarityAlgorithmsEstimationModeBusinessFacade(algorithmEstimationTemplate);
5960
var similarityAlgorithms = new SimilarityAlgorithms(progressTrackerCreator, requestScopedDependencies);
@@ -77,6 +78,8 @@ public static SimilarityApplications create(
7778
algorithmProcessingTemplateConvenience
7879
);
7980

81+
var writeRelationshipService = new WriteRelationshipService(log, requestScopedDependencies, writeContext);
82+
8083
var writeModeFacade = new SimilarityAlgorithmsWriteModeBusinessFacade(
8184
estimationModeFacade,
8285
similarityAlgorithms,

applications/facade/src/main/java/org/neo4j/gds/applications/ApplicationsFacade.java

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@
1919
*/
2020
package org.neo4j.gds.applications;
2121

22-
import org.neo4j.gds.algorithms.similarity.WriteRelationshipService;
2322
import org.neo4j.gds.applications.algorithms.centrality.CentralityApplications;
2423
import org.neo4j.gds.applications.algorithms.community.CommunityApplications;
2524
import org.neo4j.gds.applications.algorithms.embeddings.NodeEmbeddingApplications;
2625
import org.neo4j.gds.applications.algorithms.machinelearning.MachineLearningApplications;
2726
import org.neo4j.gds.applications.algorithms.machinery.AlgorithmEstimationTemplate;
2827
import org.neo4j.gds.applications.algorithms.machinery.AlgorithmProcessingTemplate;
2928
import org.neo4j.gds.applications.algorithms.machinery.AlgorithmProcessingTemplateConvenience;
30-
import org.neo4j.gds.applications.algorithms.machinery.DefaultAlgorithmProcessingTemplate;
31-
import org.neo4j.gds.applications.algorithms.machinery.MemoryGuard;
3229
import org.neo4j.gds.applications.algorithms.machinery.MutateNodeProperty;
3330
import org.neo4j.gds.applications.algorithms.machinery.ProgressTrackerCreator;
3431
import org.neo4j.gds.applications.algorithms.machinery.RequestScopedDependencies;
@@ -47,8 +44,6 @@
4744
import org.neo4j.gds.core.loading.GraphStoreCatalogService;
4845
import org.neo4j.gds.core.model.ModelCatalog;
4946
import org.neo4j.gds.logging.Log;
50-
import org.neo4j.gds.memest.DatabaseGraphStoreEstimationService;
51-
import org.neo4j.gds.metrics.algorithms.AlgorithmMetricsService;
5247
import org.neo4j.gds.metrics.projections.ProjectionMetricsService;
5348
import org.neo4j.graphdb.GraphDatabaseService;
5449
import org.neo4j.graphdb.Transaction;
@@ -105,43 +100,23 @@ public final class ApplicationsFacade {
105100
public static ApplicationsFacade create(
106101
Log log,
107102
ExportLocation exportLocation,
108-
Optional<Function<AlgorithmProcessingTemplate, AlgorithmProcessingTemplate>> algorithmProcessingTemplateDecorator,
109103
Optional<Function<GraphCatalogApplications, GraphCatalogApplications>> graphCatalogApplicationsDecorator,
110104
Optional<Function<ModelCatalogApplications, ModelCatalogApplications>> modelCatalogApplicationsDecorator,
111105
FeatureTogglesRepository featureTogglesRepository,
112106
GraphStoreCatalogService graphStoreCatalogService,
113-
MemoryGuard memoryGuard,
114-
AlgorithmMetricsService algorithmMetricsService,
115107
ProjectionMetricsService projectionMetricsService,
116108
RequestScopedDependencies requestScopedDependencies,
117109
WriteContext writeContext,
118110
ModelCatalog modelCatalog,
119111
ModelRepository modelRepository,
120112
GraphDatabaseService graphDatabaseService,
121-
Transaction procedureTransaction
113+
Transaction procedureTransaction,
114+
ProgressTrackerCreator progressTrackerCreator,
115+
AlgorithmEstimationTemplate algorithmEstimationTemplate,
116+
AlgorithmProcessingTemplate algorithmProcessingTemplate
122117
) {
123-
var databaseGraphStoreEstimationService = new DatabaseGraphStoreEstimationService(
124-
requestScopedDependencies.getGraphLoaderContext(),
125-
requestScopedDependencies.getUser()
126-
);
127-
var algorithmEstimationTemplate = new AlgorithmEstimationTemplate(
128-
graphStoreCatalogService,
129-
databaseGraphStoreEstimationService,
130-
requestScopedDependencies
131-
);
132-
133-
var algorithmProcessingTemplate = createAlgorithmProcessingTemplate(
134-
log,
135-
algorithmProcessingTemplateDecorator,
136-
graphStoreCatalogService,
137-
memoryGuard,
138-
algorithmMetricsService,
139-
requestScopedDependencies
140-
);
141118
var algorithmProcessingTemplateConvenience = new AlgorithmProcessingTemplateConvenience(algorithmProcessingTemplate);
142119

143-
var progressTrackerCreator = new ProgressTrackerCreator(log, requestScopedDependencies);
144-
145120
var mutateNodeProperty = new MutateNodeProperty(log);
146121

147122
var centralityApplications = CentralityApplications.create(
@@ -223,15 +198,13 @@ public static ApplicationsFacade create(
223198
mutateNodeProperty
224199
);
225200

226-
var writeRelationshipService = new WriteRelationshipService(log, requestScopedDependencies, writeContext);
227-
228201
var similarityApplications = SimilarityApplications.create(
229202
log,
230203
requestScopedDependencies,
231204
algorithmEstimationTemplate,
232205
algorithmProcessingTemplateConvenience,
233206
progressTrackerCreator,
234-
writeRelationshipService
207+
writeContext
235208
);
236209

237210
return new ApplicationsFacadeBuilder()
@@ -248,27 +221,6 @@ public static ApplicationsFacade create(
248221
.build();
249222
}
250223

251-
private static AlgorithmProcessingTemplate createAlgorithmProcessingTemplate(
252-
Log log,
253-
Optional<Function<AlgorithmProcessingTemplate, AlgorithmProcessingTemplate>> algorithmProcessingTemplateDecorator,
254-
GraphStoreCatalogService graphStoreCatalogService,
255-
MemoryGuard memoryGuard,
256-
AlgorithmMetricsService algorithmMetricsService,
257-
RequestScopedDependencies requestScopedDependencies
258-
) {
259-
var algorithmProcessingTemplate = DefaultAlgorithmProcessingTemplate.create(
260-
log,
261-
algorithmMetricsService,
262-
graphStoreCatalogService,
263-
memoryGuard,
264-
requestScopedDependencies
265-
);
266-
267-
if (algorithmProcessingTemplateDecorator.isEmpty()) return algorithmProcessingTemplate;
268-
269-
return algorithmProcessingTemplateDecorator.get().apply(algorithmProcessingTemplate);
270-
}
271-
272224
private static GraphCatalogApplications createGraphCatalogApplications(
273225
Log log,
274226
ExportLocation exportLocation,

proc/common/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ dependencies {
1717
api(project(':model-catalog-api'))
1818

1919
implementation project(':algo-common')
20+
implementation project(':algorithms-machinery')
2021
implementation project(':algorithms-procedure-facade')
2122
implementation project(':annotations')
2223
implementation project(':config-api')

proc/common/src/main/java/org/neo4j/gds/GraphStoreUpdater.java

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,16 @@
2121

2222
import org.neo4j.gds.api.Graph;
2323
import org.neo4j.gds.api.GraphStore;
24+
import org.neo4j.gds.applications.algorithms.machinery.GraphStoreService;
25+
import org.neo4j.gds.config.AlgoBaseConfig;
2426
import org.neo4j.gds.config.MutateNodePropertyConfig;
25-
import org.neo4j.gds.core.huge.FilteredNodePropertyValues;
2627
import org.neo4j.gds.core.write.NodeProperty;
2728
import org.neo4j.gds.executor.ComputationResult;
2829
import org.neo4j.gds.executor.ExecutionContext;
29-
import org.neo4j.gds.result.AbstractResultBuilder;
3030
import org.neo4j.gds.logging.Log;
31+
import org.neo4j.gds.result.AbstractResultBuilder;
3132

32-
import java.util.Collection;
33-
import java.util.HashSet;
3433
import java.util.List;
35-
import java.util.stream.Collectors;
3634

3735
/**
3836
* Extracting some common code so that it is reusable; eventually this can probably move to where it is used
@@ -57,38 +55,25 @@ public static <ALGO extends Algorithm<ALGO_RESULT>, ALGO_RESULT, CONFIG extends
5755
);
5856
}
5957

58+
/**
59+
* Let's eventually get rid of this
60+
*/
61+
@Deprecated
6062
public static void updateGraphStore(
6163
Graph graph,
6264
GraphStore graphStore,
6365
AbstractResultBuilder<?> resultBuilder,
64-
MutateNodePropertyConfig mutatePropertyConfig,
66+
AlgoBaseConfig configuration,
6567
Log log,
6668
final List<NodeProperty> nodePropertyList
6769
) {
68-
var maybeTranslatedProperties = graph
69-
.asNodeFilteredGraph()
70-
.map(filteredGraph -> nodePropertyList
71-
.stream()
72-
.map(nodeProperty -> NodeProperty.of(
73-
nodeProperty.key(),
74-
FilteredNodePropertyValues.OriginalToFilteredNodePropertyValues.create(
75-
nodeProperty.values(),
76-
filteredGraph
77-
)
78-
))
79-
.collect(Collectors.toList()))
80-
.orElse(nodePropertyList);
81-
82-
// TODO: stop using Neo4j Log...
83-
log.info("Updating in-memory graph store");
84-
Collection<NodeLabel> labelsToUpdate = mutatePropertyConfig.nodeLabelIdentifiers(graphStore);
85-
86-
maybeTranslatedProperties.forEach(nodeProperty -> graphStore.addNodeProperty(
87-
new HashSet<>(labelsToUpdate),
88-
nodeProperty.key(),
89-
nodeProperty.values()
90-
));
70+
var nodePropertiesWritten = new GraphStoreService(log).addNodeProperties(
71+
graph,
72+
graphStore,
73+
configuration,
74+
nodePropertyList
75+
);
9176

92-
resultBuilder.withNodePropertiesWritten(maybeTranslatedProperties.size() * graph.nodeCount());
77+
resultBuilder.withNodePropertiesWritten(nodePropertiesWritten.value());
9378
}
9479
}

proc/community/src/integrationTest/java/org/neo4j/gds/labelpropagation/LabelPropagationMutateProcTest.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
import org.neo4j.gds.api.User;
4949
import org.neo4j.gds.api.nodeproperties.ValueType;
5050
import org.neo4j.gds.applications.ApplicationsFacade;
51+
import org.neo4j.gds.applications.algorithms.machinery.DefaultAlgorithmProcessingTemplate;
5152
import org.neo4j.gds.applications.algorithms.machinery.MemoryGuard;
53+
import org.neo4j.gds.applications.algorithms.machinery.ProgressTrackerCreator;
5254
import org.neo4j.gds.applications.algorithms.machinery.RequestScopedDependencies;
5355
import org.neo4j.gds.applications.algorithms.machinery.WriteContext;
5456
import org.neo4j.gds.catalog.GraphProjectProc;
@@ -500,27 +502,33 @@ private GraphDataScienceProcedures constructFacade() {
500502
.with(EmptyUserLogRegistryFactory.INSTANCE)
501503
.build();
502504

503-
504505
var configurationParser = new UserSpecificConfigurationParser(new ConfigurationParser(DefaultsConfiguration.Instance, LimitsConfiguration.Instance),requestScopedDependencies.getUser());
505506

506507
var genericStub = new GenericStub(configurationParser, null);
508+
var algorithmProcessingTemplate = DefaultAlgorithmProcessingTemplate.create(
509+
logMock,
510+
new AlgorithmMetricsService(new PassthroughExecutionMetricRegistrar()),
511+
graphStoreCatalogService,
512+
MemoryGuard.DISABLED,
513+
requestScopedDependencies
514+
);
507515
var applicationsFacade = ApplicationsFacade.create(
508516
logMock,
509517
null,
510518
Optional.empty(),
511519
Optional.empty(),
512-
Optional.empty(),
513520
null,
514521
graphStoreCatalogService,
515-
MemoryGuard.DISABLED,
516-
new AlgorithmMetricsService(new PassthroughExecutionMetricRegistrar()),
517522
null,
518523
requestScopedDependencies,
519524
WriteContext.builder().build(),
520525
null,
521526
null,
522527
null,
523-
null
528+
null,
529+
new ProgressTrackerCreator(logMock, requestScopedDependencies),
530+
null,
531+
algorithmProcessingTemplate
524532
);
525533
var communityProcedureFacade = LocalCommunityProcedureFacade.create(
526534
applicationsFacade.community(),

0 commit comments

Comments
 (0)