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

Syntax descriptions of the different operations over node properties
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
Table 1. Parameters
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.

Table 2. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads. Note, this procedure is always running single-threaded.

Table 3. Results
Name Type Description

nodeId

Integer

The id of the node.

propertyValue

  • Integer

  • Float

  • List of Integer

  • List of Float

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
Table 4. Parameters
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.

Table 5. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads. Note, this procedure is always running single-threaded.

Table 6. Results
Name Type Description

nodeId

Integer

The id of the node.

nodeProperty

String

The name of the node property.

propertyValue

  • Integer

  • Float

  • List of Integer

  • List of Float

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
Table 7. Parameters
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.

Table 8. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads used for running the procedure. Also provides the default value for writeConcurrency

writeConcurrency

Integer

'concurrency'

The number of concurrent threads used for writing the node properties.

Table 9. Results
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
Table 10. Parameters
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.

Table 11. Configuration
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.

Table 12. Results
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
Table 13. Parameters
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.

Table 14. Configuration
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

writeConcurrency

Integer

'concurrency'

The number of concurrent threads used for writing the node properties.

Table 15. Results
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
Table 16. Parameters
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.

Table 17. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads. Note, this procedure is always running single-threaded.

Table 18. Results
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.

The following Cypher statement will create the example graph in the Neo4j database:
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)
Project the small social network graph:
CALL gds.graph.project(
  'socialGraph',
  {
    Person: {properties: "age"},
    Book: {}
  },
  ['KNOWS', 'READ']
)
Compute the Degree Centrality in our social graph:
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.

Stream the 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
Table 19. Results
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.

Stream the 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
Table 20. Results
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.

Stream multiple node properties:
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
Table 21. Results
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:

Write the score property back to Neo4j:
CALL gds.graph.nodeProperties.write('socialGraph', ['score'])
YIELD propertiesWritten
Table 22. Results
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.

Write node properties of a specific projected node label to Neo4j:
CALL gds.graph.nodeProperties.write('socialGraph', ['score'], ['Person'])
YIELD propertiesWritten
Table 23. Results
propertiesWritten

3

If the nodeLabels parameter is specified, it is required that all given node labels have all of the given properties.

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:

Add the 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
Table 24. Results
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:

Stream the 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
Table 25. Results
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:

Write the Reader node label back to Neo4j:
CALL gds.alpha.graph.nodeLabel.write('socialGraph', 'Reader', { nodeFilter: 'n.score > 0.0' })
YIELD graphName, nodeCount, nodeLabel, nodeLabelsWritten
Table 26. Results
graphName nodeCount nodeLabel nodeLabelsWritten

"socialGraph"

4

"Reader"

2

Query the Reader node label:
MATCH (n:Reader) RETURN n.name AS name, labels(n) AS labels
ORDER BY name ASC
Table 27. Results
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

Remove the score property from all projected nodes in the socialGraph:
CALL gds.graph.nodeProperties.drop('socialGraph', ['score'])
YIELD propertiesRemoved
Table 28. Results
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.

Table 29. Catalog Functions
Name Description

gds.util.nodeProperty

Allows accessing a node property stored in a named graph.

3.1. Syntax

Name Description

gds.util.nodeProperty(graphName: STRING, nodeId: INTEGER, propertyKey: STRING, nodeLabel: STRING?)

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.

Access a property node property for Florentin:
MATCH (florentin:Person {name: 'Florentin'})
RETURN
  florentin.name AS name,
  gds.util.nodeProperty('socialGraph', id(florentin), 'score') AS score
Table 30. Results
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.

Access a property node property from Person for Florentin:
MATCH (florentin:Person {name: 'Florentin'})
RETURN
  florentin.name AS name,
  gds.util.nodeProperty('socialGraph', id(florentin), 'score', 'Person') AS score
Table 31. Results
name score

"Florentin"

2.0