Writing node properties and labels
It is possible to persist computed node properties into a Neo4j database.
We refer to this operation as writing.
This is similar to what an algorithm write execution mode does, but allows more fine-grained control over the operations.
Syntax
CALL gds.graph.nodeProperties.write(
graphName: String,
nodeProperties: String or Map of Strings or List of Strings and/or Maps of Strings,
nodeLabels: String or List of Strings,
configuration: Map
)
YIELD
writeMillis: Integer,
propertiesWritten: Integer,
graphName: String,
nodeProperties: String or List of String,
configuration: Map
| Name | Type | Optional | Description |
|---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeProperties |
String, Map of Strings, or List of Strings and/or Maps of Strings |
no |
The node properties in the graph to write back. To write back properties with new custom names, store them as entries inside maps in the form: |
nodeLabels |
String or List of Strings |
yes |
The node labels to write back their node properties. |
configuration |
Map |
yes |
Additional parameters to configure writeNodeProperties. |
| Name | Type | Default | Optional | Description |
|---|---|---|---|---|
Integer |
4 [1] |
yes |
The number of concurrent threads used for running the algorithm. |
|
writeConcurrency |
Integer |
'concurrency' |
yes |
The number of concurrent threads used for writing the node properties. |
1. In a GDS Session, the default is the number of available processors. |
||||
| Name | Type | Description |
|---|---|---|
writeMillis |
Integer |
Milliseconds for writing result data back to Neo4j. |
propertiesWritten |
Integer |
Number of properties written. |
graphName |
String |
The name of a graph stored in the catalog. |
nodeProperties |
String or List of String |
The written node properties. |
configuration |
Map |
The configuration used to run the procedure. |
CALL gds.graph.nodeLabel.write(
graphName: String,
nodeLabel: String,
configuration: Map
)
YIELD
writeMillis: Integer,
nodeLabelsWritten: Integer,
nodeLabel: String,
graphName: String,
nodeCount: Integer,
configuration: Map
| Name | Type | Optional | Description |
|---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeLabel |
String |
no |
The node label to write back. |
configuration |
Map |
yes |
Additional parameters to configure writeNodeProperties. |
| Name | Type | Default | Optional | Description |
|---|---|---|---|---|
nodeFilter |
String |
n/a |
no |
A Cypher predicate for filtering nodes in the input graph. See Projecting a subgraph. |
Integer |
4 [2] |
yes |
The number of concurrent threads used for running the algorithm. |
|
2. In a GDS Session, the default is the number of available processors. |
||||
| Name | Type | Description |
|---|---|---|
writeMillis |
Integer |
Milliseconds for writing result data back to Neo4j. |
nodeLabelsWritten |
Integer |
Number of node labels written. |
graphName |
String |
The name of a graph stored in the catalog. |
nodeLabel |
String |
The written node label. |
nodeCount |
Integer |
The total number of nodes in the graph. |
configuration |
Map |
The configuration used to run the procedure. |
Examples
|
All the examples below should be run in an empty database. The examples use Cypher projections as the norm. Native projections will be deprecated in a future release. |
In order to demonstrate the GDS capabilities over node properties, we are going to create a small social network graph in Neo4j and project it into our graph catalog.
CREATE
(florentin:Person { name: 'Florentin', age: 16 }),
(adam:Person { name: 'Adam', age: 18 }),
(veselin:Person { name: 'Veselin', age: 20 }),
(hobbit:Book { name: 'The Hobbit', numberOfPages: 310 }),
(florentin)-[:KNOWS { since: 2010 }]->(adam),
(florentin)-[:KNOWS { since: 2018 }]->(veselin),
(adam)-[:READ]->(hobbit)
MATCH (n:Person)-[r:KNOWS|READ]->(m:Person|Book)
RETURN gds.graph.project('socialGraph', n, m,
{
sourceNodeLabels: labels(n),
targetNodeLabels: labels(m),
sourceNodeProperties: n { .age },
targetNodeProperties: CASE WHEN m:Person THEN m { .age } ELSE {} END,
relationshipType: type(r)
}
)
CALL gds.degree.mutate('socialGraph', {mutateProperty: 'score'})
Write node properties
To write the 'score' property for all node labels in the social graph, we use the following query:
score property back to Neo4j:CALL gds.graph.nodeProperties.write('socialGraph', ['score'])
YIELD propertiesWritten
| propertiesWritten |
|---|
4 |
The above example requires the score property to be present on at least one projected node label, and the properties will be written for all such labels.
Renaming properties when writing back
It is possible to rename node properties and write them back to the database under a custom name.
For this, you can use a map where each entry is a tuple {nodeProperty: 'renamedProperty'} i.e., the key corresponds to an existing node property in the in-memory graph and the value corresponds to the name to be written back to the database.
For convenience, a map may hold more than one entries.
The nodeProperties configuration parameter accepts both strings and maps and any combination of the two inside a list.
This can be helpful when we only want to rename a handful of properties.
age and score properties back to Neo4j with a new name for score:CALL gds.graph.nodeProperties.write('socialGraph', ['age', {score: 'writtenScore'}])
YIELD nodeProperties
| nodeProperties |
|---|
["age", "writtenScore"] |
In the above example, we write age back to the database with its default name whereas we renamed score to writtenScore by using a map.
NodeLabels
The procedure can be configured to write just the properties for some specific node labels.
In the following example, we will only write back the scores of the Person nodes.
CALL gds.graph.nodeProperties.write('socialGraph', ['score'], ['Person'])
YIELD propertiesWritten
| propertiesWritten |
|---|
3 |
|
If the |
Write Node Label
To write a new node label to the database for nodes with score higher than 0, we use the following query:
Reader node label back to Neo4j:CALL gds.graph.nodeLabel.write('socialGraph', 'Reader', { nodeFilter: 'n.score > 0.0' })
YIELD graphName, nodeCount, nodeLabel, nodeLabelsWritten
| graphName | nodeCount | nodeLabel | nodeLabelsWritten |
|---|---|---|---|
"socialGraph" |
4 |
"Reader" |
2 |
Reader node label:MATCH (n:Reader) RETURN n.name AS name, labels(n) AS labels
ORDER BY name ASC
| name | labels |
|---|---|
"Adam" |
["Person", "Reader"] |
"Florentin" |
["Person", "Reader"] |
As we can see from the database Veselin who has score: 0.0 is not a Reader.