Node operations
The graphs in the Neo4j Graph Data Science Library support properties for nodes.
We provide multiple operations to work with the stored node-properties in projected graphs.
Node properties are either added during the graph projection or when using the mutate
mode of our graph algorithms.
To inspect stored values, the gds.graph.nodeProperties.stream
procedure can be used.
This is useful if we ran multiple algorithms in mutate
mode and want to retrieve some or all of the results.
To persist the values in a Neo4j database, we can use gds.graph.nodeProperties.write
.
Similar to streaming node properties, it is also possible to write those back to Neo4j.
This is similar to what an algorithm write
execution mode does, but allows more fine-grained control over the operations.
We can also remove node properties from a named graph in the catalog. This is useful to free up main memory or to remove accidentally added node properties.
1. Syntax
CALL gds.graph.nodeProperty.stream(
graphName: String,
nodeProperties: String,
nodeLabels: String or List of Strings,
configuration: Map
)
YIELD
nodeId: Integer,
propertyValue: Integer or Float or List of Integer or List of Float
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeProperties |
String |
no |
The node property in the graph to stream. |
nodeLabels |
String or List of Strings |
yes |
The node labels to stream the node properties for graph. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
nodeId |
Integer |
The id of the node. |
propertyValue |
|
The stored property value. |
CALL gds.graph.nodeProperties.stream(
graphName: String,
nodeProperties: String or List of Strings,
nodeLabels: String or List of Strings,
configuration: Map
)
YIELD
nodeId: Integer,
nodeProperty: String,
propertyValue: Integer or Float or List of Integer or List of Float
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeProperties |
String or List of Strings |
no |
The node properties in the graph to stream. |
nodeLabels |
String or List of Strings |
yes |
The node labels to stream the node properties for graph. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
nodeId |
Integer |
The id of the node. |
nodeProperty |
String |
The name of the node property. |
propertyValue |
|
The stored property value. |
CALL gds.graph.nodeProperties.write(
graphName: String,
nodeProperties: String or List of Strings,
nodeLabels: String or List of Strings,
configuration: Map
)
YIELD
writeMillis: Integer,
propertiesWritten: Integer,
graphName: String,
nodeProperties: String or List of String
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeProperties |
String or List of Strings |
no |
The node properties in the graph to write back. |
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 | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads used for running the procedure. Also provides the default value for |
writeConcurrency |
Integer |
'concurrency' |
The number of concurrent threads used for writing the node properties. |
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. |
CALL gds.alpha.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 | Description |
---|---|---|---|
nodeFilter |
String |
n/a |
A Cypher predicate for filtering nodes in the input graph. See Projecting a subgraph. |
concurrency |
Integer |
4 |
The number of concurrent threads used for running the procedure. |
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. |
CALL gds.alpha.graph.nodeLabel.mutate(
graphName: String,
nodeLabel: String,
configuration: Map
)
YIELD
mutateMillis: Integer,
graphName: String,
nodeLabel: String,
nodeLabelsWritten: Integer,
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 | Description |
---|---|---|---|
nodeFilter |
String |
n/a |
A Cypher predicate for filtering nodes in the input graph. See Projecting a subgraph. |
concurrency |
Integer |
4 |
The number of concurrent threads used for running the procedure. Also provides the default value for |
writeConcurrency |
Integer |
'concurrency' |
The number of concurrent threads used for writing the node properties. |
Name | Type | Description |
---|---|---|
mutateMillis |
Integer |
Milliseconds for writing result data back to the in-memory graph. |
nodeLabel |
String |
The name of the label that was added to the in-memory graph. |
nodeLabelsWritten |
Integer |
Number of node labels written. |
graphName |
String |
The name of a graph stored in the catalog. |
nodeCount |
Integer |
The total number of nodes in the graph. |
configuration |
Map |
The configuration used to run the procedure. |
CALL gds.graph.nodeProperties.drop(
graphName: String,
nodeProperties: String or List of Strings,
configuration: Map
)
YIELD
propertiesRemoved: Integer,
graphName: String,
nodeProperties: String or List of String
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
nodeProperties |
String or List of Strings |
no |
The node properties in the graph to remove. |
configuration |
Map |
yes |
Additional parameters to configure removeNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
propertiesRemoved |
Integer |
Number of properties removed. |
graphName |
String |
The name of a graph stored in the catalog. |
nodeProperties |
String or List of String |
The removed node properties. |
2. Examples
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)
CALL gds.graph.project(
'socialGraph',
{
Person: {properties: "age"},
Book: {}
},
['KNOWS', 'READ']
)
CALL gds.degree.mutate('socialGraph', {mutateProperty: 'score'})
2.1. Stream
We can stream node properties stored in a named in-memory graph back to the user.
This is useful if we ran multiple algorithms in mutate
mode and want to retrieve some or all of the results.
This is similar to what an algorithm stream
execution mode does, but allows more fine-grained control over the operations.
2.1.1. Single property
In the following, we stream the previously computed scores score
.
score
node property:CALL gds.graph.nodeProperty.stream('socialGraph', 'score')
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, propertyValue AS score
ORDER BY score DESC
name | score |
---|---|
"Florentin" |
2.0 |
"Adam" |
1.0 |
"Veselin" |
0.0 |
"The Hobbit" |
0.0 |
The above example requires all given properties to be present on at least one node projection, and the properties will be streamed for all such projections. |
2.1.2. NodeLabels
The procedure can be configured to stream just the properties for specific node labels.
score
property for Person
nodes:CALL gds.graph.nodeProperty.stream('socialGraph', 'score', ['Person'])
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, propertyValue AS score
ORDER BY score DESC
name | score |
---|---|
"Florentin" |
2.0 |
"Adam" |
1.0 |
"Veselin" |
0.0 |
It is required, that all specified node labels have the node property.
2.1.3. Multiple Properties
We can also stream several properties at once.
CALL gds.graph.nodeProperties.stream('socialGraph', ['score', 'age'])
YIELD nodeId, nodeProperty, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, nodeProperty, propertyValue
ORDER BY name, nodeProperty
name | nodeProperty | propertyValue |
---|---|---|
"Adam" |
"age" |
18 |
"Adam" |
"score" |
1.0 |
"Florentin" |
"age" |
16 |
"Florentin" |
"score" |
2.0 |
"Veselin" |
"age" |
20 |
"Veselin" |
"score" |
0.0 |
When streaming multiple node properties, the name of each property is included in the result. This adds with some overhead, as each property name must be repeated for each node in the result, but is necessary in order to distinguish properties. |
2.2. Write
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.
2.2.1. 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 |
2.3. Mutate Node Label
To mutate the in-memory graph by adding a new node label for nodes with score higher than 0
, we use the following query:
Reader
node label to the in-memory graph:CALL gds.alpha.graph.nodeLabel.mutate('socialGraph', 'Reader', { nodeFilter: 'n.score > 0.0' })
YIELD graphName, nodeLabel, nodeLabelsWritten, nodeCount
graphName | nodeLabel | nodeLabelsWritten | nodeCount |
---|---|---|---|
"socialGraph" |
"Reader" |
2 |
4 |
As we can see from the result there were two nodes that matched the specified filter and they received the node label Reader
.
We can inspect the result by streaming back the score
property of the Reader
node label, we can do that using the following query:
score
property for Reader
nodes:CALL gds.graph.nodeProperty.stream('socialGraph', 'score', ['Reader'])
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, propertyValue AS score
ORDER BY score DESC
name | score |
---|---|
"Florentin" |
2.0 |
"Adam" |
1.0 |
If we compare the result to the one from the NodeLabels example we can see that Veselin
has not been labelled as a Reader
because the score
property for that node is 0
.
2.4. 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.alpha.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
.
2.5. Remove
score
property from all projected nodes in the socialGraph
:CALL gds.graph.nodeProperties.drop('socialGraph', ['score'])
YIELD propertiesRemoved
propertiesRemoved |
---|
4 |
The above example requires all given properties to be present on at least one projected node label. |
3. Utility functions
Utility functions allow accessing specific nodes of in-memory graphs directly from a Cypher query.
Name | Description |
---|---|
|
Allows accessing a node property stored in a named graph. |
3.1. Syntax
Name | Description |
---|---|
|
Named graph in the catalog, Neo4j node id, node property key and optional node label present in the named-graph. |
If a node label is given, the property value for the corresponding projection and the given node is returned.
If no label or '*'
is given, the property value is retrieved and returned from an arbitrary projection that contains the given propertyKey.
If the property value is missing for the given node, null
is returned.
3.2. Examples
We use the socialGraph
with the property score
introduced above.
MATCH (florentin:Person {name: 'Florentin'})
RETURN
florentin.name AS name,
gds.util.nodeProperty('socialGraph', id(florentin), 'score') AS score
name | score |
---|---|
"Florentin" |
2.0 |
We can also specifically return the score
property from the Person
projection in case other projections also have a score
property as follows.
MATCH (florentin:Person {name: 'Florentin'})
RETURN
florentin.name AS name,
gds.util.nodeProperty('socialGraph', id(florentin), 'score', 'Person') AS score
name | score |
---|---|
"Florentin" |
2.0 |
Was this page helpful?